使用C编写文本查看程序

wko9yo5t  于 2023-03-29  发布在  其他
关注(0)|答案(2)|浏览(118)

Stephen Prata编写的第6版教科书 C Primer Plus 的第**13章“文件输入/输出”中有以下内容:
为了给文本文件的处理带来一些规律性,C提供了两种访问文件的方法:二进制模式和文本模式。在二进制模式下,程序可以访问文件的每个字节。然而,在文本模式下,程序看到的内容可能与文件中的内容不同。使用文本视图,当读取文件时,本地环境对诸如行结束或文件结束之类的内容的表示被Map到C视图。类似地,C视图被Map到输出的本地表示。例如,在较旧的Macintosh上编译并使用文本模式的C程序在以文本模式阅读文件时会将\r转换为\n,在写入文件时会将\n转换为\r。或者在MS-DOS平台上编译的C文本模式程序会将\r\n转换为\n,而在阅读文件时将\n转换为\r\n。为其他环境编写的文本模式程序也会进行类似的调整。
您并不局限于只能使用文本文件的文本视图。您也可以使用同一文件的二进制视图。如果您对旧的MS-DOS文本文件使用二进制视图,您的程序可以看到文件中的\r和\n字符;如果你想写一个文本查看程序,比如说,旧的Mac格式、MS-DOS格式和Unix/Linux,你可以使用二进制模式,这样程序就可以确定实际的文件内容并相应地进行操作。
如果写一个文本查看程序,使用二进制模式的推理对我来说没有任何意义。如果我们的目标是写一个文本查看程序,如果C的文件文本视图自动Map二进制值(本地环境的表示)到文本视图(无论文件是MS-DOS文本文件、旧Mac文本文件还是其他文件)那么为什么使用二进制视图很重要呢?如果我理解正确的话,本地环境的二进制视图和C的文本视图之间的所有Map都是自动完成的,那么为什么我们不使用文本视图而不是二进制视图呢?作者似乎暗示这里有一些重要的区别,这意味着我们应该使用二进制视图,但我没看到。也许我忽略了一些细微的差别。

busg9geu

busg9geu1#

当你在文本模式下打开一个文件时,它假定文件格式适合你运行程序的操作系统。
但是假设你在Unix上运行这个程序,但是想写一个为Windows创建文件的程序,如果它以文本模式写文件,它将使用\n作为换行符,但是Windows需要\r\n
因此,您的程序应该以二进制模式打开该文件,并显式地写入\r\n
这是一件非常不寻常的事情,很少有应用程序会这样做。通常情况下,程序会假设它们正在处理适合当前操作系统的文件。当在操作系统之间传输文件时,我们使用单独的格式转换程序。例如,您可以在Linux上使用dos2unix从从Windows复制的文本文件中删除\r字符。

t9aqgxwy

t9aqgxwy2#

DOS文本文件中的那些\r字符是文件大小的一部分。
如果加载一行(或整个文件),由驱动程序筛选,去掉`\r ',则加载的字节数将小于文件系统报告的文件字节数...
一个C程序员需要意识到这一点。
这是一个DOS文件(它的\r\n字符是明确的)。它有5个重复的行。

0123456789\r\n0123456789\r\n0123456789\r\n0123456789\r\n0123456789\r\n

这里有一个程序加载了这5 *(10+2)字节:

#include <stdio.h>

int main( void ) {
    FILE *fp;
    char buf[100];

    fp = fopen( "foo.txt", "rb" );
    /* omitting test */
    printf( "%zu bytes\n", fread( buf, sizeof buf[0], sizeof buf, fp ) );
    fseek( fp, 0, SEEK_END );
    printf( "%zu bytes\n", ftell( fp ) );
    fclose( fp );

    fp = fopen( "foo.txt", "rt" );
    /* omitting test */
    printf( "%zu bytes\n", fread( buf, sizeof buf[0], sizeof buf, fp ) );
    fseek( fp, 0, SEEK_END );
    printf( "%zu bytes\n", ftell( fp ) );
    fclose( fp );

    return 0;
}

输出

60 bytes
60 bytes
55 bytes
60 bytes

程序员需要知道为什么55不是60(在这个例子中)。

相关问题