【问题标题】:Very large fseek forward equivalent for stdin?标准输入的非常大的 fseek 前向等效项?
【发布时间】:2013-09-21 20:37:27
【问题描述】:

我在标准输入上有一个非常大的已知字节数,并希望在读取感兴趣的部分之前丢弃大量(也已知)字节(换句话说,我想 fseek 向前一个大整数,但 fseek 没有为管道定义)。实现这一点的最简单方法似乎是对 fgetc 的大量调用,第一种替代方法是使用单个调用 fread 并分配一个大的临时指针来存储结果。第一个非常慢,第二个无缘无故地使用了可能无限量的内存。进行多次较小的读取可以解决无限的内存使用问题,但会引入一个空闲参数(块大小),该参数可能对于每台机器和操作系统组合具有不同的最快值。

是否有任何替代方案能够以简洁、高效的方式实现这一目标?假定为 POSIX。

【问题讨论】:

    标签: c stdin fread fseek


    【解决方案1】:

    没有办法“跳过”管道上的数据 - 您必须阅读它。

    如果它是一个非常大的块,您将需要使用中等大小的缓冲区(作为开销和内存使用之间的折衷),如下所示:

     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 是一个相当随意的选择 - 但它足够大,不会对输入造成大量读取,并且足够小,不会使用大量堆栈空间。您不太可能从更改此大小中获得/损失太多。

    【讨论】:

    • @CharlieBurns:是的,我想过这个问题,然后“偏离了方向”,确保我得到了正确的 fread 参数(因为我总是想把“文件”作为第一个参数,并且永远无法真正记住中间的“计数”和“大小”......)
    • 一旦你修复了我的评论。不用担心。这是一个明显的疏忽。
    • 您的 4096 是我原始问题中的免费参数。在大多数感兴趣的体系结构上,由于这是页面大小或与页面大小合理相关,因此可能存在速度优势。但是,malloc 缓冲区而不是为其声明堆栈空间会更快吗?后者是否保证任何形式的对齐?
    • 它可能具有页面大小的一些优势,但它不会自动对齐。很可能不值得调用malloc,因为这比在堆栈上腾出空间所需的单条指令要长得多,并且要获得它,你需要获得很多 - 我怀疑fread 不是'不会那么好。
    • 这是有道理的,尽管如果您要为许多相同或更少大小的寻道重用相同的缓冲区,那么大概有一个点,单个 malloc() 调用是值得的。 fread(buffer, 1, toread, stdin) 和 fread(buffer, toread, 1, stdin) 之间是否存在速度差异?对您的答案的另一个小更正:在 C 中没有为整数定义 min()。
    猜你喜欢
    • 1970-01-01
    • 2021-06-15
    • 2011-06-22
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    相关资源
    最近更新 更多