预计阅读本页时间:-
编程从文件读取信息或者将结果写入文件是一种经常性的需求。程序和文件进行通信的一种方式就是文件重定向,这在第8章“字符串输入/输出和输入确认”中已经学习过。这种方法很简单不过有局限性。例如,假定您要编写一个交互式程序,向用户询问书名,然后将完整的列表保存在一个文件中。如果像下面这样使用重定向:
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
程序给出的交互式提示就会被重定向到bklist。这不仅会导致将不希望的文本写入bklist,而且用户也将无法看到需要回答的问题。
幸运的是,C提供了功能更为强大的文件通信方法。使用这种方法您可以在程序中打开文件,然后使用专门的I/O函数读取文件或者写入文件。在研究这些方法以前,我们首先简要地看一下文件的特性。
13.1.1 文件是什么
一个文件(file)通常就是磁盘上的一段命名的存储区。比如stdio.h就是一个包含一些有用信息的文件的名称。但对于操作系统来说,文件就会更复杂一些。例如,一个大文件可以存储在一些分散的区段中,或者还会包含一些使操作系统可以确定其文件类型的附加数据,但是这些是操作系统而不是程序员(除非您是在编写操作系统)要考虑的。您需要考虑的是如何在C程序中处理文件。
C将文件看成是连续的字节序列,其中每一个字节都可以单独地读取。这与UNIX环境(C的发源地)中的文件结构是一致的。因为其他的环境中的文件模型可能会有所不同,所以ANSI C提供了文件的两种视图:文本视图和二进制视图。
13.1.2 文本视图和二进制视图
ANSI要求提供的两种文件视图是文本视图和二进制视图。在二进制视图中,文件中的每个字节都可以为程序所访问。在文本视图中,程序看到的内容和文件的内容有可能不同。例如,使用文本视图读取文件时,将把行尾的本地环境表示法映射为C视图。与之类似,在输出的时候,也会将C视图中的行尾表示映射为本地环境表示法。例如,MS-DOS文本文件用回车符和换行符的组合\r\n来表示行尾。Macintosh文本文件只用一个回车符\r来表示行尾。C程序使用一个\n表示行尾。所以,如果C程序以文本视图模式处理一个MS-DOS文本文件,在读取文件时它会将\r\n转换为\n,在写入文件的时候它会将\n转换成为\r\n;而对于Macintosh文本文件的文本视图,在读取文件时它会将\r转换成为\n,在写入文件的时候它会将\n转换成为\r。
处理一个MS-DOS文本文件不必局限于仅仅使用文本视图。对这样的文件还可以使用二进制视图。如果是这样,程序将看到文件中的\r和\n字符,没有任何映射发生(请参见图13.1)。MS-DOS区分文本文件和二进制文件,但C提供的是文本和二进制视图。通常,对于文本文件使用文本视图,对于二进制文件使用二进制视图。但是,您也可以使用任一种视图处理任一种文件,尽管用文本视图处理二进制文件的效果很糟。
图13.1 二进制视图和文本视图
尽管ANSI C提供了文本视图和二进制视图,但这两种视图的实现可以是相同的。例如,由于UNIX仅采用一种文件结构,所以这两种视图在UNIX实现中就是相同的。
13.1.3 I/O级别
除了可以选择文件的视图,在大多数情况下,您还可以在两个I/O级别(即两种处理文件存取的级别)中进行选择。低级I/O(low-level I/O)使用操作系统提供的基本I/O服务;标准高级VO(standard high-level I/O)使用一个标准的C库函数包和stdio.h头文件中的定义。因为无法保证所有的操作系统都可以用相同的低级I/O模型表示,所以ANSI C只支持标准I/O包。由于ANSI C建立了标准I/O模型的可移植性,我们也将集中讨论它。
13.1.4 标准文件
C程序自动为您打开3个文件。这3个文件被称为标准输入(standard input),标准输出(standard output)和标准错误输出(standard error output)。默认的标准输入是系统的一般输入设备,通常为键盘;默认的标准输出和标准错误输出是系统的一般输出设备,通常为显示器。
用标准输入为您的程序提供输入是很自然的事情,它是getchar()、gets()和scanf()读取的文件。标准输出是常用的程序输出对象,为putchar()、puts()和printf()所使用。在第8章中学过的重定向方法可以把其他文件作为标准输入或者标准输出。标准错误输出提供一个可供发送错误消息的逻辑上不同的位置。例如,如果使用重定向方法将输出发送到一个文件中而不是屏幕上,发送到标准错误输出的输出内容仍然会被发送到屏幕上。这样很好,因为如果错误信息被发送到文件的话,那么只有打开文件才可以看到。