我只想读取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标准的操作系统? (在提供所有相关功能的系统上。)
答案 0 :(得分:2)
如果基础文件描述符是可搜索的(常规文件或块设备,除非你的系统上有其他奇怪的可搜索对象......)那么你要做的就没有意义了。只需使用ftello
获取FILE
中的逻辑位置,然后放弃FILE
并使用sendfile
。在用户空间中使用已经缓冲的数据实际上比sendfile
慢。
如果基础文件描述符不可搜索,则整个方法不起作用,因为lseek
将始终返回-1而ftello
将返回EOF
。在这种情况下的潜在解决方案:
dup
创建一个引用相同打开文件描述的新文件描述符。/dev/null
只写,dup2
在FILE
使用的旧文件描述符编号之上。FILE
读取将成功,直到缓冲区耗尽,然后给出读取错误,因为文件描述符现在引用了一个不可读的文件。fclose
FILE
。{/ li> {{1}}
答案 1 :(得分:1)
对于Unix平台上的可搜索文件,您应该能够使用fflush()来协调基于fd *的使用,包括用于阅读。完整的详细信息在http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01和http://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html中提供。
这是标准C为您提供的扩展(不出所料)。
答案 2 :(得分:0)
我不相信stdio API可以保证这适用于任何系统。例如,如果它注意到缓冲区为空,它可能会执行readahead。
你的“解决方案”最多只是一个具体的实施黑客。