【问题标题】:C: lseek() related questionC: lseek() 相关问题
【发布时间】:2011-02-04 03:53:24
【问题描述】:

我想在一个文件中写一些 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”文件。strong text

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

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)。

【问题讨论】:

    标签: c posix


    【解决方案1】:

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      另外,我不确定您所说的“我的空白空间在哪里?”。

      【讨论】:

      • 从我的书中:“就其本身而言,越过文件末尾没有任何作用——对新创建的文件位置的读取请求将返回 EOF。如果随后对该位置发出写入请求,但是,在文件的旧长度和新长度之间将创建新的空间,并将用零填充。"我现在意识到零不是空格。是因为那些零我无法使用常规文本编辑器打开文件吗?
      • “无法打开”是什么意思?当你尝试时会发生什么?如果您想知道到底发生了什么,请查看文件的十六进制转储(例如,通过打开您的 shell 并执行 cat helloworld|xxd)
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-17
        相关资源
        最近更新 更多