gpt4 book ai didi

c - ftell(FILE* fd) 和 lseek(int fd, off_t offset, int whence) 结果之间的区别

转载 作者:行者123 更新时间:2023-12-01 22:52:29 27 4
gpt4 key购买 nike

考虑这个代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
//this file exists and contains data: "ABCDEFGHIJKLM"
FILE* file = fopen("file.txt", "r");
char data[4];
long int pos = ftell(file);
fseek(file, 0, SEEK_SET);
fread(data, 4, 1, file);
fseek(file, pos, SEEK_SET);

printf("ftell: %d\n", ftell(file));
printf("lseek: %d\n", lseek(fileno(file), 0, SEEK_CUR));

fread(data, 1, 4, file);

//this correctly prints A
//but external function needs fileno(file) that has wrong pos
printf("%c\n", data[0]);

fclose(file);
return 0;
}

这个程序的结果令人惊讶:

ftell: 0
lseek: 14
A

我正在尝试修复我的应用程序中的错误,但我确定该程序不久前的结果应该是 0, 0(换句话说,以前从未有过这个我的应用程序出错)。

发生这种奇怪情况的 libc 发生了什么变化?

我怎样才能很好地解决这个问题?

lseek(fileno(file), 0, SEEK_SET) 是一个好的解决方案吗?

最佳答案

同时使用标准库文件操作(例如 fread(3)fseek(3))和低级系统调用(例如 读取(2)lseek(3))。

这是有问题的原因是因为标准库会缓冲东西,而不是立即将它们写出(到文件描述符)(取决于缓冲模式)。

如果你需要访问底层文件描述符,你应该确保fflush在获取其 fileno 之前的流。我在头文件中抛出了这样的东西:

/**
* Safely get the file descriptor associated with FILE,
* by fflush()ing its contents first.
*/
static inline int safe_fileno(FILE *f)
{
fflush(f);
return fileno(f);
}

此外,一旦你调用它,你可能不应该再次返回使用 FILE*,因为你已经改变了内核文件指针,但标准库可能会认为它没有改变(因为你上次 fflush 编辑了它)。如前所述in a comment ,您可以像这样将 FILE* 与文件描述符重新同步:

/**
* Re-synchronize the file offset of a FILE with the
* file offset of its underlying file descriptor.
*/
static inline void fresync(FILE *f)
{
off_t off = lseek(fileno(f), 0, SEEK_CUR);
fseek(f, off, SEEK_SET);
}

关于c - ftell(FILE* fd) 和 lseek(int fd, off_t offset, int whence) 结果之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31687964/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com