如何在C中正确打印文件内容到命令行?

时间:2017-03-24 17:00:41

标签: c linux

我想将.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无效?

3 个答案:

答案 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};

在这种情况下,在读取文件后使用%sprintf打印这样的缓冲区将起作用,只是假设读取没有初始化完整数组,其中的字节为none,为0。

附加

Null terminating一个字符串意味着你在某处附加一个0。这就是大多数字符串相关函数猜测字符串结束的位置。

答案 2 :(得分:3)

  

为什么strlen不工作?

因为当您在read(fd, buffer, strlen(buffer));中调用它时,尚未将有效字符串分配给buffer。它包含一些不确定的数据,这些数据可能有也可能没有0值元素。根据您报告的行为,buffer恰好恰好在元素4处有一个0,但这不可靠。

第三个参数告诉read从文件描述符中读取多少字节 - 如果要读取与buffer一样多的字节大小以保持,请使用sizeof bufferread将返回从fd读取的字节数(0表示EOF,-1表示错误)。 IINM,read对输入进行零终止,因此在调用strlenbuffer上使用read 仍然 >是个错误。