这一定是一个愚蠢的问题,因为这应该是一个非常常见和简单的问题,但我在任何地方都找不到答案,所以我会咬紧牙关问。
在无法确定数据大小的情况下,究竟应该如何从标准输入中读取数据?显然,如果数据以NUL或EOF之类的终止符结尾,那么这是非常简单的,但我的数据不是。这是一个简单的IPC:两个程序需要来回对话,用EOF结束文件流会破坏一切。
我觉得这应该很简单。很明显,程序总是通过管道相互对话,而不需要任何神秘的技巧,所以我希望有一个简单的答案,我太蠢了,没想到。我试过的都没用。
一些显而易见的事情,比如(为了简洁而忽略必要的realloc):
int size = 0, max = 8192;
unsigned char *buf = malloc(max);
while (fread((buf + size), 1, 1, stdin) == 1)
++size;
由于fread()阻塞并等待数据,因此无法工作,因此此循环不会终止。据我所知,stdio中没有允许非阻塞输入的东西,所以我甚至没有尝试任何这样的函数。这是我能想到的最好的办法:
struct mydata {
unsigned char *data;
int slen; /* size of data */
int mlen; /* maximum allocated size */
};
...
struct mydata *buf = xmalloc(sizeof *buf);
buf->data = xmalloc((buf->mlen = 8192));
buf->slen = 0;
int nread = read(0, buf->data, 1);
if (nread == (-1))
err(1, "read error");
buf->slen += nread;
fcntl(0, F_SETFL, oflags | O_NONBLOCK);
do {
if (buf->slen >= (buf->mlen - 32))
buf->data = xrealloc(buf->data, (buf->mlen *= 2));
nread = read(0, (buf->data + buf->slen), 1);
if (nread > 0)
buf->slen += nread;
} while (nread == 1);
fcntl(0, F_SETFL, oflags);
其中
oflags
是一个全局变量,包含stdin的原始标志(在程序开始时缓存,以防万一)。这种愚蠢的方法只要所有的数据都立即出现就可以工作,但如果不这样做就会失败。因为这将read()设置为非阻塞,所以如果没有数据,它只返回-1。与矿井通信的程序通常在任何时候都会发送响应,而不是一次响应,所以如果数据完全大,则退出太早而失败。 最佳答案
在无法确定数据大小的情况下,究竟应该如何从标准输入中读取数据?
总有一种方法来决定大小。否则,程序将需要无限的内存,因此不可能在物理计算机上运行。
这样想:即使在数据流永无止境的情况下,也必须有一些块或点需要处理它。例如,直播视频必须解码其中的一部分(例如帧)。或者一个视频游戏,它一个接一个地处理信息,即使游戏的长度不确定。
无论您决定使用哪种类型的I/O(阻塞/非阻塞、同步/异步…),这都是正确的。例如,如果您想使用典型的阻塞同步I/O,您需要做的是在循环中处理数据:每次迭代,您读取尽可能多的可用数据,并尽可能多地处理。无论你不能处理什么(因为你还没有收到足够的信息),你都要为下一次迭代做好准备。然后,循环的其余部分就是程序逻辑的其余部分。
最后,不管你做什么,你(或其他人,如库、操作系统、硬件缓冲区……)都必须缓冲传入的数据,直到它可以被处理为止。
关于c - 从C中的stdin读取不可预测且不确定(即没有EOF)大小的输入的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51003956/