Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/182.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
确定标准尺寸的正确/有效方法(C)_C_Size_Stdin - Fatal编程技术网

确定标准尺寸的正确/有效方法(C)

确定标准尺寸的正确/有效方法(C),c,size,stdin,C,Size,Stdin,基于我前面的问题,如果stdin来自不同系统上的管道或终端,那么确定stdin大小的正确而有效的方法是什么 #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; } 然而,根据一些评论,我做了以下工作,这不是正确的方法,它可能在不

基于我前面的问题,如果stdin来自不同系统上的
管道
终端
,那么确定
stdin
大小的正确而有效的方法是什么

#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;
}
然而,根据一些评论,我做了以下工作,这不是正确的方法,它可能在不同的系统上工作,也可能不工作

#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;
}
#包括
关闭大小(文件*st_英寸){
结构统计;
如果(fstat(fileno(st_-in),&st)==0)
返回st.st_大小;
返回-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; 
}
#包括
#包括
关闭大小(文件*st_in){
结构统计;
off_t retval=-1;
如果(!isatty(文件号(st_in))
{
如果(fstat(fileno(st_-in),&st)==0)
{
if(S_ISREG(st.st_模式)
retval=标准标准尺寸;
}
其他的
{
perror(“无法统计文件”);
出口(1);
}
}   
返回返回;
}
出口在那里(可选)。如果需要,您可以在其他地方处理问题。

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


你所问的和“水龙头里有多少水”是一样的:-)与前面所说的相反,你可以使用
stat()
确定某些操作系统中管道或流中的数据量。但是,这不会在所有系统上都起作用——也就是说,提供此功能不是实现的标准做法,因此以这种方式进行操作将不可移植

还有一个问题是,每当有人向管道中写入更多数据时,管道大小就会发生变化,这基本上可以在多任务、抢占式系统中随时发生

因此,尽管你可以小心翼翼地绕过你想做的事情,但这是一个脆弱且不可移植的解决方案

当然,在EOF或error之前读取每个字节并计数仍然有效。不过,不确定这是您想要的。

在某些系统(我知道,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;
}
#包括
#包括
ssize_t fd_ready_size(int fd){
int sz;
int rc;
rc=ioctl(fd、FIONREAD和sz);
如果(rc){//rc=-1或0
返回rc;
}
返回sz;
}
对于大多数输入文件。你应该注意,我没有在这里传入
文件*
。我这样做是因为它会产生误导。stdio文件可以缓冲其中的数据,这些数据需要添加到操作系统所说的任何准备好读取的文件中。这让事情变得更加棘手,我不知道是否有是获得该值的合理方法

我返回了一个
ssize\t
(这是一种有符号大小类型),因为这是POSIX系统下读写操作返回的值,-1表示错误情况


如果你使用的系统不允许你这样做,而stat不能提供你想要的东西,你可能不得不采取一些技巧。一种方法是尝试读取一定大小的数据(我们称之为X),如果你成功获得了这个完整的数据,你可以想“可能还有一点”并重新锁定缓冲区以容纳更多数据,并重复操作,直到读取的数据没有完全填满可用的空间。如果您有任何类型的轮询函数可用(您可能在调用stat后就使用了该函数),则您也可以使用该函数尝试不调用读取函数,除非您确定存在数据(除非您以非阻塞方式打开文件,在这种情况下,这无关紧要)。

文件
ANSI C中的对象表示流。就个人而言,我会将类型命名为
,而不是
文件
,但这是另一个问题

无论如何,
FILE
对象表示信息流。一些流源表示一块数据。这些源是文件和内存块。其他流源,如管道和套接字连接,不表示一块数据。它们表示(可能的)无限字节流。没有明确的开始,因为管道可能已经从前面读取,然后重定向到您。也没有明确的结束,因为数据可能会永远到达流上(或者至少直到有人关闭电源;)

stdin
表示一种管道类型的流。它没有明确的起点和终点。因此无法可靠地测量


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

管道没有文件大小。如果您写入管道,它的大小将发生变化。@terminus:您能重新读取stdina吗nd获取新的大小?@terminus-Solaris pipes返回一个带有统计信息的大小。请阅读Stevens和Rago的主题。我不知道我们这里有什么操作系统。因此您的评论在大多数地方都是有效的,而不是所有地方。谢谢大家清理它!为什么您需要知道大小?只需阅读直到找到结尾或阅读足够的内容。是否可以测量自从你打开它,直到我决定检查它为止,已经流了多少水?呵呵,这和问一样,例如,“从那个水龙头里拿5加仑。”。如果水龙头连接到配水系统,您不会有问题;如果它连接到一个3加仑的桶,您可能会有问题。好的,但我仍然想知道,如果我这样做,例如
tail-f file | myprog
其中“file”包含
例如:20行(假设X字节数)
,则我将知道我已从stdin中读取了X个字节。因此,如果在“文件”中添加新行,占该行的1个额外字节,则我将知道当前