[英]C: lseek() related question
我想在文件中写一些伪造的文本(在名为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)。
在此函数调用write(fildes, fname, buf_size)
, fname
具有10个字符(加上尾随的'\\ 0'字符,但是您要告诉该函数写出16个字节。 fname
字符串。
另外,我不确定“我的空白在哪里?”的意思。
您的buf_size与fname的长度不匹配。 它正在通过缓冲区读取数据,因此会获得或多或少的随机字节,这些字节恰好位于内存中的字符串之后。
除了期望零等于相等的空间外,最初的问题确实是写的超出了“ helloworld”字符串的长度。 为避免此类问题,我建议让编译器为您计算常量字符串的长度:
write(fildes, fname, sizeof(fname) - 1)
- 1
是由于NUL字符(零, \\0
)用于终止C样式的字符串,而sizeof
只是返回保存该字符串的数组的大小。 因此,您不能在运行时使用sizeof
来计算字符串的实际长度,但是它对于编译时常量很有效。
在原始测试中看到的“ Can”几乎可以肯定是代码中"\\nCannot"
字符串之一的开头; 在将11个字节写入"helloworld\\0"
您继续从内存中紧随其后的内容写入剩余的字节,这原来是下一个字符串常量。 (该问题现已修改为写入10个字节,但最初发布的版本写入了16个字节。)
文本文件中NUL字符(=零, '\\0'
)的存在确实可能导致某些(但不是全部)文本编辑器考虑文件二进制数据而不是文本,并可能拒绝打开它。 文本文件应仅包含文本,而不包含控制字符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.