我编写了一个程序来读取文本文件,将所有文件内容发送到消息队列,并在控制台中显示。我所拥有的文本文件大小从30kb到30mb不等。现在我的程序最多只能读取1024个字节。我应该设置MAX以便读取所有文件内容?或者是其他地方的问题?请指教。非常感谢您的帮助。
#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);
}
答案 0 :(得分:1)
如果您想使用缓冲区,我们的想法是选择代表您要处理的最有意义的数据量的最小大小。对于您正在构建的体系结构,读取字大小块的倍数是很常见的。
请记住,读取大量字节并将其存储在堆栈中是非常糟糕的。这将极易受到堆栈溢出的影响。如果你必须将它存储在内存中,那么最大的空间就是内存池。有一些技巧可以解决这个问题:一次处理有意义的字节数(而不是整个文件)。这就是动态数组或其他ADT的概念发挥作用的地方。
对于“读取文件并将其输出到控制台”的特定情况,它实际上比您想象的要容易得多。您可以一次读取一个字节,直到EOF
并将其输出到stdout
。不需要队列或任何东西。
编辑:根据您的要求,我提出的解决方案示例:
for ( int byte = getchar(); byte != EOF; byte = getchar() ) {
printf( "%c", byte );
}
......就是这样。一次只处理一个字节。然后,您可以将文本文件传输到程序:
./program < textfile.txt
答案 1 :(得分:1)
一次将一个大的(多兆字节)文件读入堆栈分配的缓冲区是一个坏主意,因为如果缓冲区超过堆栈大小,您将获得堆栈溢出。我相信Windows上的默认堆栈大小为1 MB,Linux上为8 MB。 (这取决于编译器吗?)
此外,堆栈数组具有固定的大小(无论如何都是C89),因此您必须猜测最大可能文件的大小,然后分配足够大的缓冲区来容纳它,这可能非常浪费。
如果出于某种原因需要在内存中同时使用该文件,则需要使用malloc()
堆分配缓冲区。但是,最好在固定大小的缓冲区中一次操作一小段文件。这将允许您在堆栈上安全地分配缓冲区,并且内存效率更高。