C:lseek()相关问题

时间:2010-04-04 08:57:09

标签: c posix

我想在文件中写一些 bogus 文本(名为 helloworld 的文件中的“helloworld”文本),但不是从头开始。我在考虑 lseek()功能。

如果我使用以下代码(已修改):

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

#define fname "helloworld"
#define buf_size 16

int main(){

    char buffer[buf_size];
    int fildes,
        nbytes;
    off_t ret;

    fildes = open(fname, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
    if(fildes < 0){
        printf("\nCannot create file + trunc file.\n");
    }
//modify offset
    if((ret = lseek(fildes, (off_t) 10, SEEK_END)) < (off_t) 0){
        fprintf(stdout, "\nCannot modify offset.\n");
    }
    printf("ret = %d\n", (int)ret);

    if(write(fildes, fname, 10) < 0){
        fprintf(stdout, "\nWrite failed.\n");
    }

    close(fildes);

    return (0);
}

,编译良好,运行时没有任何明显的错误。 仍然如果我:

cat helloworld

输出不是我的预期,但是:

helloworld
Can

“Can”来自哪里,我的空格在哪里?

我应该期待“零”而不是空格吗?如果我尝试使用gedit打开helloworld,则会发生错误,抱怨文件字符编码未知。

稍后编辑: 在用正确的缓冲区编辑我的程序进行编写,然后再次编译/运行后,仍然无法使用gedit打开“helloworld”文件。强文

稍后编辑 我现在明白这个问题。我在代码中添加了以下内容:

fildes = open(fname, O_RDONLY);
if(fildes < 0){
    printf("\nCannot open file.\n");
}

while((nbytes = read(fildes, c, 1)) == 1){
    printf("%d ", (int)*c);     
}

现在的输出是:

0 0 0 0 0 0 0 0 0 0 104 101 108 108 111 119 111 114 108 100

我的问题是我期待空格(32)而不是零(0)。

3 个答案:

答案 0 :(得分:2)

在这个函数调用中,write(fildes, fname, buf_size)fname有10个字符(加上一个尾随的'\ 0'字符,但你告诉函数写出16个字节。谁知道在fname字符串后的内存位置。

另外,我不确定你的意思是“我的空位在哪里?”。

答案 1 :(得分:1)

你的buf_size与fname的长度不匹配。它正在读取缓冲区,因此获得或多或少的随机字节恰好位于内存中的字符串之后。

答案 2 :(得分:1)

除了期望零等于空格之外,最初的问题确实写的不仅仅是“helloworld”字符串的长度。为了避免这样的问题,我建议让编译器为你计算常量字符串的长度:

    write(fildes, fname, sizeof(fname) - 1)

- 1是由于NUL字符(零,\0)用于终止C风格的字符串,而sizeof只是返回包含C样式字符串的数组的大小串。因此,您不能使用sizeof来计算字符串在运行时的实际长度,但它适用于编译时常量。

您在原始测试中看到的“Can”几乎肯定是代码中"\nCannot"个字符串之一的开头;在"helloworld\0"中写入11个字节后,你继续从内存中跟随它的任何内容写入剩余的字节,结果证明是下一个字符串常量。 (这个问题现在已被修改为写入10个字节,但最初发布的版本写了16个。)

文本文件中存在NUL字符(= 0,'\0')可能确实会导致某些(但不是全部)文本编辑器考虑文件二进制数据而不是文本,并可能拒绝打开它。文本文件应该只包含文本,而不是控制字符。