我想在文件中写一些 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)。
答案 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'
)可能确实会导致某些(但不是全部)文本编辑器考虑文件二进制数据而不是文本,并可能拒绝打开它。文本文件应该只包含文本,而不是控制字符。