从FILE对象中只读缓冲日期

时间:2011-05-29 18:40:19

标签: c file posix buffer

我只想读取FILE对象缓冲区中已有的内容,以便之后缓冲区为空(我可以使用sendfile之类的文件描述符) 。我想出了这个函数,它似乎适用于我的64位Linux安装:

int readbuf(FILE *stream, char buf[], size_t *size) {
    off_t pos = ftello(stream);
    if (pos < 0) return -1;
    off_t realpos = lseek(fileno(stream), 0, SEEK_CUR);
    if (realpos < 0) return -1;
    if (pos > realpos) {
        errno = EIO;
        return -1;
    }
    size_t bufsize = realpos - pos;
    if (bufsize > *size) {
        *size = bufsize;
        errno = ERANGE;
        return -1;
    }
    *size = bufsize;
    if (fread(buf, bufsize, 1, stream) < 1) {
        return -1;
    }
    return 0;
}

现在我想知道,我能否认为这适用于其他符合POSIX标准的操作系统? (在提供所有相关功能的系统上。)

3 个答案:

答案 0 :(得分:2)

如果基础文件描述符是可搜索的(常规文件或块设备,除非你的系统上有其他奇怪的可搜索对象......)那么你要做的就没有意义了。只需使用ftello获取FILE中的逻辑位置,然后放弃FILE并使用sendfile。在用户空间中使用已经缓冲的数据实际上比sendfile慢。

如果基础文件描述符不可搜索,则整个方法不起作用,因为lseek将始终返回-1而ftello将返回EOF。在这种情况下的潜在解决方案:

  • 使用dup创建一个引用相同打开文件描述的新文件描述符。
  • 打开/dev/null只写,dup2FILE使用的旧文件描述符编号之上。
  • FILE读取将成功,直到缓冲区耗尽,然后给出读取错误,因为文件描述符现在引用了一个不可读的文件。
  • 此时,您可以直接从第一步中复制的fd中读取。您也可以fclose FILE。{/ li> {{1}}

答案 1 :(得分:1)

对于Unix平台上的可搜索文件,您应该能够使用fflush()来协调基于fd *的使用,包括用于阅读。完整的详细信息在http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01http://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html中提供。

这是标准C为您提供的扩展(不出所料)。

答案 2 :(得分:0)

我不相信stdio API可以保证这适用于任何系统。例如,如果它注意到缓冲区为空,它可能会执行readahead。

你的“解决方案”最多只是一个具体的实施黑客。