根据我之前的问题,如果stdin来自不同系统上的stdin
或pipe
,那么确定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;
}
答案 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)
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;
}
可选择退出。如果需要,您可以在其他地方处理问题。