如何解决找出输入缓冲区中的字节数
我正在尝试编写一个从标准输入读取的程序,其中文件被重定向到标准输入。
比如我的程序叫scan,那么命令行上的调用会是:
./scan < file.txt
我想为它分配一个大内存块,由 char*
指向。我不能只将文件名作为输入,因为这是我必须处理的要求。我想知道是否有可能计算出输入缓冲区中的字节数,以便我可以一次性批量读取 stdin。
有点像
char* read_all_stdin()
{
size_t amt = num_of_bytes_in_stdin(); //how do this?
char* file = (char*) malloc(amt+1);
fread(file,1,amt,stdin); //idk if this is allowed either
file[amt] = '\0';
return file;
}
解决方法
我想知道是否有可能计算出输入缓冲区中的字节数,以便我可以一次性批量读取 stdin。
如果您可以确定输入缓冲区中的字节数,那么它将创建一个不可避免的竞争条件 - 在您确定有多少字节之后但在您之前,可以将新的字节/字符添加到输入缓冲区已经将这个值用于任何事情。
不可避免的竞争条件的后果是“不,在实践中不可能确保一次性批量读取标准输入”。
一种替代方法是,每当“fread()”表示它填充了先前分配的内存并重试(例如使用循环和realloc()
)直到{{1}无法填充分配的内存。但是,fread()
是阻塞的(如果您要求 1024 个字节而只有 10 个字节,它将等待其他 1014 个字节到达)因此您必须通过将 fread()
更改为非-阻塞。遗憾的是,这是特定于平台的(例如,stdin
之类的东西可以在 Linux 上运行,但不能在 Windows 上运行),因此您最终会遇到一个大而复杂的混乱。
如果输入是从文件重定向的,那么在 Linux 中您可以通过读取 /proc/self/fd/0
char filename[bufsize];
int sz = readlink("/proc/self/fd/0",filename,bufsize-1);
filename[sz] = 0;
puts(filename);
其他平台可能无法实现
如果 stdin 是一个管道,那么显然你不能知道它的大小,因为操作系统在将数据传递给消费进程之前不会等待写入进程将其所有数据泵入管道
,size_t amt = num_of_bytes_in_stdin(); //how do this?
你可能会惹恼setvbuf
,但AFAIK你不能。标准输入可能不会被缓冲。流可能包含多个缓冲区已满。其他人可能已经改变了它的缓冲方式。 More might have been added between your checking,allocating,and reading。
I/O 的基本性质是你不知道你会得到什么或多少。
相反,分配一个大缓冲区来读取,可能是 BUFSIZ
。重用该缓冲区以从流中读取。然后从中复制到更合适大小的内存。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。