我在stdin上有一个非常大的已知字节数,希望在读取感兴趣的部分之前丢弃其中的大量字节(换句话说,我希望通过一个大整数向前fseek,但是没有为管道定义fseek)。实现这一点的最简单方法似乎是大量调用fgetc,第一种方法是使用对fread的单个调用,并分配一个大的scratch指针来存储结果。第一种是非常慢的,第二种是毫无理由地使用无限量的内存。进行多次较小的读取可以解决无限内存使用问题,但是引入了一个自由参数(块大小),对于每台机器和操作系统的组合,该参数可能具有不同的最快值。
有没有其他方法能以整洁、高效的方式实现这一目标?假设为POSIX。
最佳答案
无法“跳过”管道上的数据-必须读取它。
如果它是一个非常大的块,您需要使用一个中等大小的缓冲区(在开销和内存使用之间进行折衷),如下所示:
size_t dataToRead = some_large_number;
while(dataToRead)
{
char buffer[4096];
size_t toread = min(sizeof(buffer), dataToRead);
size_t nread = fread(buffer, 1, toread, stdin);
dataToRead -= nread;
}
4096的大小是一个相当随意的选择,但它足够大,不会对输入造成大量的读取,并且足够小,不会占用大量的堆栈空间。你不太可能从改变这个尺寸中得到很多好处。