c - lseek 稀疏文件与常规文件的比较导致意外结果?

标签 c unix

据我所知,我一直在阅读高级 unix 编程书籍。对文件使用 lseek 并创建一个洞应该使用更少的磁盘空间,因为该洞没有记录在磁盘上并且该洞用零填充。

但是我创建了两个文件,一个有孔,一个没有,但是没有孔的文件比有孔的文件占用更少的磁盘空间。我想我可能搞砸了代码,但我不确定我是如何得到这些结果的。因为这似乎与我对文件漏洞的理解相矛盾。这两个文件不应该大小相同吗?

我可能从根本上完全忽略了 lseek 的使用要点?如果是这样,请随意投反对票,因为我知道只允许最高质量的帖子。并解释我在这里缺少什么?谢谢。

使用 lseek 编写代码

#include "apue.h"
#include <fcntl.h>

char buf1[] = "abcdefghik";
char buf2[] = "ABCDEFGHIJ";

int main (void)
{
    int fd;

    if((fd = creat("file.hole" , FILE_MODE)) < 0)
            err_sys("creat error");

    if(write(fd , buf1 , 10) != 10)
            err_sys("buf1 write error");

    //offset now = 10 becaues we wrote 10 bytes

    if(lseek(fd , 16384 , SEEK_SET) == -1)
            err_sys("lseek error");
    /*offset now = 16384 there is now a hole*/

    if(write(fd , buf2 , 10) != 10)
            err_sys("buf2 write error");
    /*offset now 16384 + 10 bytes = 16394*/

    exit(0);

//now have a gap in file, however this gap is not written to the disk. so doesn't take up all that space on the disk
}

没有 lseek 的代码

#include "apue.h"
#include <fcntl.h>

char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";

int main (void){
    int fd;

    //creating new file
    if((fd = creat("file.nohole" , FILE_MODE)) < 0)
            err_sys("create error");

    //writing 10 bytes of buf1
    if(write(fd,buf1,10) != 10)
            err_sys("write buf1 error");
    //writing 10 bytes of buf2
    if(write(fd,buf2,10) != 10)
            err_sys("write buf2 error");

    exit(0);

    //no hole in the file.
}

od -c file.hole(检查内容)

0000000   a   b   c   d   e   f   g   h   i   k  \0  \0  \0  \0  \0  \0
0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0040000   A   B   C   D   E   F   G   H   I   J
0040012

od -c file.nohole(检查内容)

0000000   a   b   c   d   e   f   g   h   i   j   A   B   C   D   E   F
0000020   G   H   I   J
0000024

比较两个文件 - ls -ls file.hole file.nohole

28 -rw-r--r-- 1 sam sam 16394 Jul 10 14:09 file.hole
12 -rw-r--r-- 1 sam sam    20 Jul 10 14:32 file.nohole

最佳答案

有洞的文件将数据存储在两个单独的磁盘 block 上。

没有空洞的文件,数据存储在一个磁盘 block 上。

ls 报告的大小是文件中的字节数,而不是存储在磁盘 block 中的字节数。丢失的字节全为零,od -c 的输出清楚地表明了这一点。

请注意,使用 lseek() 的目的不是在文件中创建漏洞。这些是实现细节。使用lseek() 的原因是将文件中的读/写位置放在下一个要读取或写入的位置。例如,在一个固定大小记录的文件中,可以使用lseek(fd, N * sizeof(struct Record), SEEK_SET)找到第N条记录,然后读取(或写入)数据在那个位置。

关于c - lseek 稀疏文件与常规文件的比较导致意外结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45013933/

相关文章:

用于将文件移动到训练目录或测试目录的 Python 脚本

c - C 中指针减法期间的除法

c - 如何交换指针数组中的元素

unix - 如何查看共享对象的内部属性?

python - 无法将 django 更新到最新版本

linux - 如何根据上一个命令比较得到下一个输入命令[bash-script]

c++ - 我们应该使用 poll() 还是 select()?

c - 使用C语言在文件中搜索字符串

c - TI CC2530 - 将 float 转换为 uint8[] 以进行发送,然后在接收中转换回 float

c - 有多个 fork 和额外的打印品