ftell函数在C中为stdout赋予-1

时间:2011-10-09 17:49:34

标签: c popen

我想用C语言,我正在使用popen这样做。

FILE *stdoutPtr = popen(command,"r");
fseek(stdoutPtr, 0L, SEEK_END);
long pos = ftell(stdoutPtr);

这里我希望获得stdout的大小,以便我可以初始化缓冲区。但pos变量始终为-1。 pos应该告诉我读指针的当前位置。

请帮忙......

2 个答案:

答案 0 :(得分:6)

FILE返回的popen不是常规文件,而是pipe。 (这就是p所代表的含义。)数据从您调用到程序的命令的标准输出中管道。因为它是通信通道而不是磁盘上的文件,所以管道没有确定的大小,并且您无法在数据流中寻找不同的位置。因此,fseek and ftell在应用于此FILE时都会失败,这就是-1返回值的含义。如果您在调用errno后立即检查ftell,您会发现它的值为ESPIPE,这意味着“您不能对管道执行此操作。”

如果您尝试将命令的所有输出读入单个char*缓冲区,唯一的方法是重复调用其中一个读取函数,直到它指示文件结束,并根据需要使用realloc扩大缓冲区。如果输出可能很大,那么最好更改程序以处理数据块,如果有任何方法可以做到这一点。

答案 1 :(得分:1)

你不能以这种方式使用管道。首先,当您获得信息时,信息就会过时,因为那时可以将更多数据写入管道。您必须使用不同的分配策略。

最常见的策略是分配固定大小的缓冲区,然后继续阅读,直到到达文件末尾。如果您愿意,可以在阅读时处理数据。

如果您需要在一个块中处理所有数据,则可以分配一个大缓冲区并开始读取。如果确实已满,请使用realloc扩大缓冲区并继续运行直到完成所有操作。

常见的模式是保留缓冲区指针,缓冲区计数和分配大小。最初,将分配大小设置为64K。将计数设置为零。分配64K缓冲区。将最多size-count个字节读入缓冲区。如果你点击EOF,请停止。如果缓冲区接近满,则将分配大小提高50%并缓冲区realloc