【问题标题】:Figure out number of bytes in input buffer计算输入缓冲区中的字节数
【发布时间】:2021-04-02 23:45:14
【问题描述】:

我正在尝试编写一个从标准输入读取的程序,其中文件被重定向到标准输入。

比如我的程序叫做scan,那么命令行的调用会是:

./scan < file.txt

我想为其分配一个大内存块,由char* 指向。我不能只将文件名作为输入,因为这是我必须处理的要求。我想知道是否可以计算出输入缓冲区中的字节数,以便我可以一次性批量读取标准输入。

类似

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;
}

【问题讨论】:

  • 不要费心尝试预先确定您需要多少空间。一次读取一个字符并根据需要增加缓冲区。可以在github.com/wrp/examples/blob/main/c/dynamic-array.c 看到一个例子
  • @WilliamPursell:你的 GitHub 提供了大量的好例子(例如(a-&gt;start &lt; a-&gt;end) ? *a-&gt;start++ : EOF)!

标签: c stdin io-redirection


【解决方案1】:

如果输入是从文件重定向的,那么在 Linux 中,您可以通过读取 /proc/self/fd/0get the name of that file

char filename[bufsize];
int sz = readlink("/proc/self/fd/0", filename, bufsize-1);
filename[sz] = 0;
puts(filename);

在其他平台可能无法实现

如果标准输入是一个管道,那么显然你无法知道它的大小,因为操作系统不会等待写入进程将其所有数据泵入管道,然后再将数据传递给消费进程

【讨论】:

    【解决方案2】:

    我想知道是否可以计算出输入缓冲区中的字节数,以便我可以一次性批量读取标准输入。

    如果您可以确定输入缓冲区中的字节数,那么它会产生不可避免的竞争条件 - 在您确定有多少字节之后但在您之前,可以将新字节/字符添加到输入缓冲区'已经将该值用于任何事情。

    不可避免的竞争条件的后果是“不,实际上不可能确保您可以一次性批量读取标准输入”。

    当“fread()”说它填满了先前分配的内存并重试(例如使用循环和realloc())时,一个替代方案是增加(加倍?)分配内存的大小,直到fread() 不能填充分配的内存。但是,fread() 是阻塞的(如果您要求 1024 个字节并且只有 10 个字节,它将等待其他 1014 个字节到达)所以您必须通过将 stdin 更改为非阻塞来解决这个问题。遗憾的是,这是特定于平台的(例如,flags = fcntl(0, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(0, F_SETFL, val); 之类的东西可能适用于 Linux,但不适用于 Windows),因此您最终会遇到一大堆复杂的问题。

    【讨论】:

      【解决方案3】:
      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。重用该缓冲区从流中读取。然后从那里复制到更合适大小的内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-28
        • 2017-12-02
        • 1970-01-01
        • 1970-01-01
        • 2017-10-31
        • 1970-01-01
        • 2018-01-28
        • 1970-01-01
        相关资源
        最近更新 更多