如何使用底层POSIX函数检查当前写入位置是否在文件末尾?第一个想法是使用lseek和fstat:
off_t sk;
struct stat st;
sk = lseek (f, 0, SEEK_CUR);
fstat (f, &st);
return st->st_size == sk;
但是,是否st->st_size反映实际大小而不反映磁盘文件大小,即不包括内核缓冲的数据?
另一个想法是使用
off_t scur, send;
scur = lseek (f, 0, SEEK_CUR);
send = lseek (f, 0, SEEK_END);
lseek (f, scur, SEEK_START);
return scur == send;
但这似乎不是快速而适当的方法。
同样,这两种方法似乎都不是原子的,因此,如果在文件后追加了另一个进程,则可以在检查当前偏移量后更改大小。
但是,是否st->st_size反映实际大小而不反映磁盘文件大小,即不包括内核缓冲的数据?
我不明白您对内核缓冲数据的意思。中的数字st->st_size反映了文件的大小(以字符为单位)。因此,如果文件包含1000000字符,则数字st->st_size将为1000000,字符位置为0到999999。
有两种方法可以在POSIX系统中获取文件大小:
做一个off_t saved = lseek(fd, 0, SEEK_END);,它返回实际位置(您必须保存它,以便以后恢复它),然后执行第二次调用off_t file_size = lseek(fd, saved, SEEK_SET);,返回到您之前的位置,但是返回一个数字来返回您之前的位置(这是该位置的最后一个位置)文件,最后一个字符之后)。如果选中此选项,它将与所返回的值匹配st->st_size。 stat(2)对文件描述符执行a 以获得您提到的值。 如果您有多个线程或进程与您共享文件描述符(通过dup(2)系统调用或fork()ed进程),如果它们在您的两个调用之间执行,或调用read(2),则第一种方法会有一些缺点。您以前在文件上的位置,将无法恢复到正确的位置。这很奇怪,并且使第一种方法不可取。write(2)lseek(2)lseek
最后,内核完成的文件缓冲与文件大小没有关系。您始终会在上获得真实的文件大小stat(2)。唯一使您感到困惑的是运行以下代码段时在内核上所做的节省(但这对您来说是透明的,您无需考虑,除非要将文件复制到另一个地点)。只需运行这个小程序:
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("file", O_WRONLY | O_CREAT | O_TRUNC, 0666);
lseek(fd, 1000000, SEEK_SET);
char string[] = "Hello, world";
write(fd, string, sizeof string);
close(fd);
}
其中以1000013字节文件结尾,但仅使用一两个磁盘空间块。那是一个空洞的文件,其中1000000您写入的字符串之前有零个字节,并且系统不会在磁盘中为其分配块。只有在这些块上进行写操作时,系统才会用新的块填充您写的部分以保存数据...但是直到那时,系统将向您显示零字节,但它们不会存储在任何地方。
$ ll file
-rw-r----- 1 lcu lcu 1000013 4 jul. 11:52 file
$ hd file
[file]:
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :................
*
000f4240: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 00 :Hello, world.
000f424d
$ _
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。