正确/有效的方法来确定C中stdin的大小

时间:2010-12-10 18:00:37

标签: c size stdin

根据我之前的问题,如果stdin来自不同系统上的stdinpipe,那么确定terminal大小的正确而有效的方法是什么。< / p>

我正在做以下事情,但是,根据一些评论,它不是正确的方式,它可能或可能不适用于不同的系统。

#include <sys/stat.h>

off_t size(FILE *st_in) {
    struct stat st;
    if (fstat(fileno(st_in), &st) == 0)
        return st.st_size;
    return -1;
}

5 个答案:

答案 0 :(得分:11)

你不能。
想象一下stdin就像一个水龙头。

您要问的是“水龙头中有多少水”? : - )

答案 1 :(得分:3)

与上述内容相反,您可以使用stat()来确定某些操作系统中管道或流中的数据量。 然而,这不适用于所有系统 - 也就是说,实现提供此功能并非标准做法,因此以这种方式执行 NOT 可移植

每当有人向其写入更多数据时,管道大小也会发生变化的问题,这种情况基本上可以在多任务,抢占式系统中随时发生。

所以,虽然你可以自己动手做你想做的事情,但这是一个微弱且不便携的解决方案。

当然,读取每个字节直到EOF或错误,并且计数仍然有效。但不确定这是你想要的。

答案 2 :(得分:2)

在某些系统(linux,我知道;可能是其他* nix)下你可以这样做:

#include <unistd.h>
#include <sys/ioctl.h>

ssize_t fd_ready_size(int fd) { 
    int sz;
    int rc;

    rc = ioctl(fd, FIONREAD, &sz);
    if (rc) { // rc = -1 or 0
        return rc;
    }
    return sz;
}

对于大多数输入文件。你应该注意我没有通过这里的FILE *。我这样做是因为它会产生误导。 stdio FILE可以在其中缓存数据,这些数据需要添加到OS准备读取的任何内容中。这使得事情变得更加棘手,如果有合理的方法来获得这个价值,我不知道如何。

我返回了ssize_t(签名大小类型),因为这是POSIX系统下读写返回的内容,-1表示错误情况。

如果您使用的系统不允许您这样做而且stat不能提供您想要的功能,那么您可能不得不采用技巧。一种方法是尝试读取一定的大小(我们将调用X),如果你成功获得这个全部数量,你可以认为“可能会有更多”并重新分配你的缓冲区来保持更多,并重复直到你得到的读数并没有完全填满你可用的空间。如果您有任何类型的轮询功能(您可能在调用stat时可能会这样做),那么您也可以使用它来尝试不调用读取函数,除非您确定有数据(除非您打开了非阻塞文件)在这种情况下没关系)。

答案 3 :(得分:2)

ANSI C中的

FILE个对象表示流。就个人而言,我会将类型命名为STREAM而不是FILE,但这是另一个问题。

无论如何,FILE个对象代表信息流。一些流源代表一大块数据。这些源是文件和内存块。其他流源(例如管道和套接字连接)不代表大量数据。它们代表(可能)无限的字节流。没有明确的开始,因为管道可能已经从早先读过,后来被重定向到你。也没有确定的结束,因为数据可能永远地到达流上(或者至少在有人关闭电源之前;)。

stdin表示流的管道类型。它没有明确的开始,也没有明确的结局。因此无法可靠地测量。

如果你想在任何特定时间知道从流中读取了多少数据,你必须在FILE函数的顶部创建一些抽象层(或以某种方式挂钩它 - 不要了解ANSI C)中的这些功能,并保留自己的记录。但请注意,您无法知道从流中读取的第一个字节是从中读取的第一个字节,因为它在读取后可能已重定向到您。

答案 4 :(得分:-1)

尝试这样的事情:

#include <sys/stat.h> 
#include <unistd.h> 
off_t size(FILE *st_in) { 
    struct stat st; 
    off_t retval=-1;
    if (! isatty(fileno(st_in))
    {
       if (fstat(fileno(st_in), &st) == 0) 
       {
           if(S_ISREG(st.st_mode)  
              retval=st.st_size; 
       }
       else
       {
           perror("Cannot stat file");
           exit(1);
       }
    }   
    return retval; 
}

可选择退出。如果需要,您可以在其他地方处理问题。