C/C中对文件的操作分以二进制文件方式读写和以文本文件方式读写两种(这里说的是文本文件,对于图像、音频文件,自然是以二进制处理)。例如,

/*以读方式打开文本文件*/FILE *fp = fopen("test.txt","r");/*以写方式打开二进制文件*/FILE *fp = fopen("test.txt","wb");

对于文本,处理的内容包括字符、数字。

对于数字,二进制存储自然是将整数用补码的方案,而浮点数是以IEE754的编码方案。数字用文本方式存储,要将单个数字转换为ASCII编码。

对于字符,二者的区别在于对换行符的处理上,不同的操作系统有所区别,其它字符的存储都是一样的。

1 回车符和换行符

回车符 Carrier Return (CR):’r’,对应ASCII的13,功能:将打字机头定位在左边界。

换行符 Line Feed (LF):’n’, 对应ASCII的10,功能:打字机把纸下移一行。

在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。

于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。

这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。

后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。

Unix 系统里,每行结尾只有“<换行>”,即“n”;Windows系统里面,每行结尾是“ <回车><换 行>”,即“rn”;Mac系统里,每行结尾是“<回车>”。一个直接后果是,Unix/Mac系统下的文件在Windows里打 开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

现在这两个功能完全没必要分,我们通常所说的“换行”都是指:光标移动到行首 光标移动到下一行。

文本文件的行结束符,windows系统用’rn’;Mac系统用’r’;Unix系统用’n’。

2 C语言windows平台下,处理二进制文件和文本文件的区别

不同计算机上c语言统一规定为:

文本文件的行结束符一律是一个符号LF,也就是换行符,也就是new line符或’n’。但在windows平台下,以文本文件方式读入到磁盘存储器中,就有所区别了。

2.1 读写文本文件

在向文本文件写入’n’时,实际上写入了’rn’(因为windows平台用’rn’表示换行)保存到了磁盘文件;

从文本文件读到换行时(’rn’)会自动将’r’舍去,只保留’n’读入到内存。

例如,执行下面的代码,

FILE *fp = fopen("test.txt","w ");fprintf(fp, "abcndef");/*写入7个字符*/

得到的文件大小为8字节,用winhex打开结果为:

可以看到文件里有8个字符,包括ASCII码为0x0D的’r’和0x0A的’n’。

同理,重新打开这个文件进行读取,会发现无法读取到’r’字符只能读到’n’。

2.2 读写二进制文件

写二进制文件,写入的是什么就是什么,并不会增加任何东西。

例如,执行下面的代码,

FILE *fp = fopen("test.txt","wb ");fprintf(fp, "abcndef");/*写入7个字符*/

得到的文件大小为7字节,用winhex打开结果为:

可以看到文件里仅有写入的7个字符。

同理,读二进制文件,读到的是什么就是什么,并不会舍去任何东西。例如,打开3.1中的文件,是可以同时读到’r’字符和’n’字符的。

2.3 总结一下:

windows系统下,读写文本文件都要对换行符做特殊处理,而读写二进制文件则不需要。

C语言中,读写文本文件用fprintf()和fscanf()等函数,这两个函数会默认处理的数据都是ASCII码;读写二进制文件用fwrite()和fread()函数。

写文本文件,将内存中的数字做转换,换行符做处理,再写入到文本中。 而写二进制文件,则是将内存里面的数值直接写入磁盘的文本中。

文本文件是为了让人阅读;二进制文件是为了让机器阅读。

一般情况下二进制文件占用空间更小,计算机处理更快。例如,保存整数1144201745(4个字节的int)。

以文本文件方式存储:

int num = 1144201745;FILE *fp = fopen("test.txt","w ");fprintf(fp, "%d", num);/*十进制方式写入*/

得到的文件大小为10字节:num有10位。

可看到,内存中存储的是num各位的ASCII码。

以二进制方式存储:

int num = 1144201745;FILE *fp = fopen("test.txt","wb ");fprintf(fp, "%d", num);/*十进制方式写入*/

得到的文件大小为4字节:num是int只占4字节。

可以看到,内存中存储的是num的二进制表示。

2.4 文件位置操作:seeking和telling

由上述内容可知,对文本存储方式数字和换行的特殊处理,文本文件在内存中的数据表示与磁盘上数据表示的长度不同,文本文件中的seeking和telling是不可靠动作(包括UI的文本框内文本的操作)。当程序需要在文件内查找和告知当前文件的位置,程序应该使用二进制模式打开文件。

3 按下Enter键,读取字符函数读到什么

键盘上的enter键对应的字符是’r’,而enter键还有额外很多功能,例如,将控制台输入写入缓冲区,并将’n’写入缓冲区。

#include <conio.h>ch=getch();// 从键盘上读入一个字符不回显直接(不需回车)送给字符变量chch=getche();// 从键盘上读入一个字符带回显直接(不需回车)送给字符变量ch#include <stdio.h>ch=getchar()// 从键盘上读入一个字符带回显 (需回车)送给字符变量chcout<<(int)ch<<endl;

使用getch(), getche()获取键盘输入时,如果按enter键,得到的是’r’,原因就在于enter键对应的字符是’r’,而这两个函数是直接获得键盘输入;

使用getchar()或scanf(“%c”, &ch)读取字符,如果按enter键,得到的是’n’,原因在于这两个函数是从缓冲区获取输入,而按enter键的作用是将控制台输入写入缓冲区,如下实例,键盘输入a,回车后,a读给了ch,'n'读给了ch2。

char ch,ch2;ch = getchar();cout<<(int)ch<<endl;scanf("%c",&ch2);cout<<(int)ch2<<endl;/*a9710/*

-End-

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如有侵权行为,请第一时间联系我们修改或删除,多谢。