Unix:当offset大于size时写入()

时间:2014-05-06 07:11:56

标签: c file unix io

我有以下代码:

 #include <ctype.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    char buf[]="wimpykid";
    char buff[100];
    void pri(int fd);
    int main(){
       int i=0,fd;
       fd=creat("ifile", S_IRUSR|S_IWUSR); pri(fd);
       write(fd, buf, 8); pri(fd);

       lseek(fd, 23, SEEK_CUR);  pri(fd);
       while(buf[i]!='\0'){
        if(i%2)
           buf[i]=toupper(buf[i]);i++;
       }
       write(fd, buf,8);  pri(fd);
    exit(0);
}
//print the current offset
void pri(int fd){
    printf("%d\n", lseek( fd, 0, SEEK_CUR));
}

输出为0,8,31,39。在第一次写入之后,偏移现在是8.文件中只有8个字符,但是如何将23添加到当前偏移量?如果我已经这样做了,当我再写8个字符时,8个字符会从哪里开始?输出显示第二个8个字符直接跟随前8个字符。我不太明白。

3 个答案:

答案 0 :(得分:2)

当您查看文件内容的(可打印部分)时,它们可能看起来像是直接相互写入的两个字符序列:

$ cat ifile
wimpykidwImPyKiD

这是因为此处不显示不可打印的字符。 当你看一下二进制数据时,你也可以看到它们:

$ hexdump -C ifile
00000000  77 69 6d 70 79 6b 69 64  00 00 00 00 00 00 00 00  |wimpykid........|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 77  |...............w|
00000020  49 6d 50 79 4b 69 44                              |ImPyKiD|
00000027

如您所见,两个字符串之间有多个零字节。这些零字节来自哪里?看一下lseek函数的手册页:

  

lseek()函数允许将文件偏移量设置为超出结束范围       的文件(但这不会改变文件的大小)。如果数据       后来写到了这一点,随后读取了数据       gap(a&#34; hole&#34;)返回空字节('\0'),直到实际数据为止       写入差距。

这些文件可以由文件系统实现为稀疏文件。

供参考:

答案 1 :(得分:0)

尝试理解这个

lseek(fd,0,SEEK_CUR)您当前的偏移值(位置= 0)

lseek(fd,1,SEEK_CUR)偏移量将从当前值增加到+1。 (位置= 1)

lseek(fd,5,SEEK_CUR)偏移量将从当前值增加到+5。 (位置= 6)

并且在将当前位置设置为23后不会跟随字符。在添加字符之前,它可能会显示一些垃圾值。

答案 2 :(得分:0)

  

...当我写另外8个字符时,8个字符将从哪里开始?

在第31位,代码是在第二次写入之前寻求的。即:0(初始位置)+8(写入8之后)+ 23(寻求23之后)= 31

做一个

hexdump ifile

给出了ifile

的内容
Offet 
in hex  Content in hex
0000000 6977 706d 6b79 6469 0000 0000 0000 0000
0000010 0000 0000 0000 0000 0000 0000 0000 7700
0000020 6d49 7950 694b 0044

请注意,在发出write()的实际呼叫之前,所搜索的23个字节不会写入文件。