1

我编写了一个程序来读取文本文件,将所有文件内容发送到消息队列,并在控制台中显示。我拥有的文本文件的大小从 30kb 到 30mb 不等。现在我的程序最多只能读取 1024 个字节。为了读取所有文件内容,我应该设置什么数字?还是其他地方的问题?请指教。非常感谢您的帮助。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define MAX 1024    //1096

//Declare the message structure
struct msgbuf
{
    long type;
    char mtext[MAX];
};


//Main Function
int main (int argc, char **argv)
{
    key_t key;      //key to be passed to msgget()
    int msgid;      //return value from msgget()
    int len;
    struct msgbuf *mesg;  //*mesg or mesg?
    int msgflg = 0666 | IPC_CREAT;
    int fd;
    char buff[MAX];


    //Initialize a message queue
    //Get the message queue id
    key = ftok("test.c", 1);
    if (key == -1)
    {
        perror("Can't create ftok.");
        exit(1);
    }

    msgid = msgget(key, msgflg);
    if (msgid < 0)
    {
        perror("Cant create message queue");
        exit(1);
    }

    //writer
    //send to the queue
    mesg=(struct msgbuf*)malloc((unsigned)sizeof(struct msgbuf));
    if (mesg == NULL)
    {
        perror("Could not allocate message buffer.");
        exit(1);
    }

    //set up type
    mesg->type = 100;

    //open file
    fd = open(argv[1], O_RDONLY);

    while (read(fd,buff,sizeof(buff))>0)
    {
        //printf("%s\n", buff);
        strcpy(mesg->mtext,buff);
    }


    if(msgsnd(msgid, mesg, sizeof(mesg->mtext), IPC_NOWAIT) == -1)
    {
        perror("Cant write to message queue");
        exit(1);
    }


    //reader
    int n;

    while ((n=msgrcv(msgid, mesg, sizeof(mesg->mtext), 100, IPC_NOWAIT)) > 0)
    {
        write(1, mesg->mtext, n);
        printf("\n");

    }

    //delete the message queue
    msgctl(msgid,IPC_RMID,NULL);

    close(fd);

}
4

2 回答 2

1

一次将一个大(多兆字节)文件读入堆栈分配的缓冲区是一个坏主意,因为如果缓冲区超出堆栈大小,您将获得堆栈溢出。我相信默认堆栈大小在 Windows 上为 1 MB,在 Linux 上为 8 MB。(这取决于编译器吗?)

此外,堆栈数组具有固定大小(无论如何在 C89 中),因此您必须猜测最大可能文件的大小,然后分配一个足够大的缓冲区来容纳它,这可能非常浪费。

如果出于某种原因您需要一次将文件全部存储在内存中,您需要使用malloc(). 但是,最好在固定大小的缓冲区中一次对文件的小块进行操作。这将允许您安全地在堆栈上分配缓冲区,并且内存效率更高。

于 2013-08-11T20:22:20.097 回答
1

如果您想使用缓冲区,则想法是选择代表您要处理的最有意义的数据量的最小大小。对于您正在构建的架构,通常会读取多个字大小的块。

但请记住,读取大量字节并将其存储在堆栈中是非常糟糕的。这将非常容易受到堆栈溢出的影响。如果必须将其存储在内存中,那么最大的空间将是内存池。有一些技巧可以解决这个问题:一次处理有意义的字节数(而不是整个文件)。这就是动态数组或其他一些 ADT 的想法发挥作用的地方。

对于您“读取文件并将其输出到控制台”的特定情况,它实际上比您想象的要容易得多。您可以一次只读取一个字节,直到EOF并将其输出到stdout. 不需要排队或任何东西。

编辑:根据您的要求,我提出的解决方案的一个示例:

for ( int byte = getchar(); byte != EOF; byte = getchar() ) {
  printf( "%c", byte );
}

......就是这样。一次只处理一个字节。然后,您可以将您的文本文件通过管道传输到程序中:

./program < textfile.txt
于 2013-08-11T20:14:11.807 回答