我想将.txt文件的内容打印到命令行,如下所示:
main() {
int fd;
char buffer[1000];
fd = open("testfile.txt", O_RDONLY);
read(fd, buffer, strlen(buffer));
printf("%s\n", buffer);
close(fd);
}
文件testfile.txt如下所示:
line1
line2
line3
line4
该功能仅打印前4个字母line
。
使用sizeof
代替strlen
时,将打印整个文件。
为什么strlen
无效?
答案 0 :(得分:6)
在此程序中使用strlen
是不正确的。在调用read
之前,缓冲区未初始化并且对其应用strlen
具有未定义的行为。在调用read
之后,缓冲区的一些字节被初始化,但缓冲区不一定是正确的C字符串; strlen(buffer)
可能返回一个与您应该打印出的数据量无关的数字,或者可能仍然有UB(如果read
使用非空字节初始化数组的全长,{{1}将走完尽头)。出于同样的原因,strlen
是错误的。
您的程序根本无法处理大于缓冲区的文件。
执行此操作的正确方法是在循环中使用printf("%s\n", buffer)
和read
的返回值。要告诉write
缓冲区有多大,请使用read
。 (注意:如果您使用sizeof
而不是本地变量分配了缓冲区,那么您可以不使用malloc
来获取其大小;您必须记住你自己的大小。)
sizeof
练习:应对短写和写错误。
答案 1 :(得分:4)
使用sizeof而不是strlen时,将打印整个文件。为什么是 strlen不工作?
因为strlen如何工作,它会通过传入的char数组并计算字符直到遇到0.在你的情况下,buffer
没有被初始化 - 因此它会尝试访问未初始化的元素数组(buffer
)查找0,但在C中不允许读取未初始化的内存。实际上,您会得到未定义的行为。
sizeof
的工作方式不同,直接返回传递对象的字节数,而不像strlen
那样在数组中查找0。
正如其他答案中正确指出的那样,读取不会为您终止字符串,因此您必须手动执行此操作或将buffer
声明为:
char buffer[1000] = {0};
在这种情况下,在读取文件后使用%s
和printf
打印这样的缓冲区将起作用,只是假设读取没有初始化完整数组,其中的字节为none,为0。
附加:
Null terminating一个字符串意味着你在某处附加一个0。这就是大多数字符串相关函数猜测字符串结束的位置。
答案 2 :(得分:3)
为什么strlen不工作?
因为当您在read(fd, buffer, strlen(buffer));
中调用它时,尚未将有效字符串分配给buffer
。它包含一些不确定的数据,这些数据可能有也可能没有0值元素。根据您报告的行为,buffer
恰好恰好在元素4处有一个0,但这不可靠。
第三个参数告诉read
从文件描述符中读取多少字节 - 如果要读取与buffer
一样多的字节大小以保持,请使用sizeof buffer
。 read
将返回从fd
读取的字节数(0表示EOF
,-1表示错误)。 IINM,read
将不对输入进行零终止,因此在调用strlen
后buffer
上使用read
仍然 >是个错误。