假设我有一个使用POSIX扩展的C程序,有一个FILE *fp
和它的文件描述符int fd
. 我可以假设fd
(按照lseek(fd, 0, SEEK_CUR)
)的"文件位置"应该与fp
(按照ftell(fp)
)的"文件位置"相匹配吗? "假设"是指"POSIX要求..."
假设我有一个使用POSIX扩展的C程序,有一个FILE *fp
和它的文件描述符int fd
. 我可以假设fd
(按照lseek(fd, 0, SEEK_CUR)
)的"文件位置"应该与fp
(按照ftell(fp)
)的"文件位置"相匹配吗? "假设"是指"POSIX要求..."
我认为可以肯定地说,你可以假设有一些情况下,他们don't匹配.
一个明显的例子是预读:stdio通常读取一个字节的块,不管应用程序要求多少字节.然后,ftell()
将根据应用程序代码读取的量来判断位置,而lseek()
将根据从操作系统读取的量来判断位置.
试试这样做:
$ cat > seek.c <<'EOF'
#include <stdio.h>
#include <unistd.h>
char buf[123];
int main(void) {
int fd = fileno(stdin);
fread(buf, 12, 3, stdin);
long pos1 = ftell(stdin);
long pos2 = lseek(fd, 0, SEEK_CUR);
printf("ftell: %ld lseek: %ld\n", pos1, pos2);
return 0;
}
EOF
$ gcc -Wall -o seek seek.c
$ ./seek < dummyfile
ftell: 36 lseek: 4096
类似地,由于写缓冲,低级fd位置将落后于stdio文件位置.
正如在 comments 中提到的,standard has instructions on what to do when accessing a single file through multiple handles(fds或stdio流).对于不同的情况,有几个步骤可以采取,但通过我的阅读,它似乎可以归结为:
fflush()
,无论它是用于读还是写).fseek()
或lseek()
.就我个人而言,我会避免陷入这种混乱.