文件操作的一个细节 - 换行符"\n"和回车符"\r"
2012-01-04 11:44
316 查看
问题始于社区的一个帖子,楼主的问题如下:
“在c语言中,对一个不知道大小的文件进行读操作,我用fread()将文件的内容先放到一个缓存区,然后将缓存区中的内容打印出来,
缓存区中的内容和文件中的内容不一样,好像是因为缓存区的空间比存储文件内容所需要的空间大了,不知道应该怎么解决”
这个问题我之前也碰到过,翻了一些C语言文件操作方面的资料,发现对于换行的处理,其实是一个从打字机时代就有的历史遗留问题:
“在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打
完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。 于是,研制人员
想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,
告诉打字机把纸向下移一行。 ”
在计算机出现之后,这种概念又被移植到了计算机操作系统上。当然,对于是否移植这一点也是有争议的,Windows和Unix/Mac系统在这一点
上就分道扬镳了。
下面首先讨论在Windows平台下的情况。
Windows平台采用了历史的概念,在文件中,换行被处理为“\r\n”两个字符,也就是说,虽然用户只敲了一次回车键,但其实系统
会认为收到了“\r\n”两个字符,并同时存储了这两个字符。
因此,在Windows平台下,文件为了存储一次换行会写入两个字符。当程序员试图从文件中读取文件内容时,C语言提供了两种方式:文本方
式和二进制方式,这两种方式又有什么区别呢?
在Windows平台下,采用文本方式打开一个文件时,会自动将一次换行,即“\r\n”两个字符转换成一个“\n”字符,即会去掉一个“\r”
字符,这种转换的结果就是:实际读取的数据长度会比文件的真实长度短,两者之差等于文件中的换行次数。而当采用二进制方式打开
一个文件时,由于二进制方式打开的特点是有什么读什么,因此,“\r\n”两个字符会原封不动,均被读取,因而实际读取的数据长度与
原文件长度相同。
由于这种区别的存在,推荐大家在读取文件时采用二进制方式,文件中是什么内容,读取到的就是什么内容。
那么,在Unix平台下呢?
Unix/Mac平台并没有采用Windows平台的方式,在Unix/Mac中,每一行的结尾只有一个换行符,即“\n”,因此,Unix/Mac平台下两种读取方式
是不会有区别的。
一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,
某些文本编辑器可能在每行的结尾会多出一个^M符号。
下面是我在Windows平台下的一段测试代码,仅供参考交流:
/****************************************************************** /*函数名:get_file_size /*功能:获取文件大小 /*输入:FILE* stream:文件路径 /*输出:int:文件大小 /****************************************************************** */ static int get_file_size(FILE *stream) { int curpos; int length; curpos = ftell(stream); fseek(stream, 0L, SEEK_END); length = ftell(stream); fseek(stream, curpos, SEEK_SET); return length; } int _tmain(int argc, _TCHAR* argv[]) { FILE *pf; char *p_buf; int file_size; int length; pf = fopen("ReadMe.txt", "rb"); if (pf == NULL) return -1; file_size = get_file_size(pf); p_buf = (char *)malloc(file_size); length = fread(p_buf, 1, file_size, pf); p_buf[length] = 0; printf("File Size : %d\n", file_size); printf("Read Size : %d\n", length); printf("%s\n", p_buf); return 0; }
相关文章推荐
- 文件操作的一个细节 - 换行符"\n"和回车符"\r"
- 一个文件操作的小细节
- 文件操作之增删改查3---文件的修改,f.replace(),在linux里的一些应用sed,with语句方法来打开一个或多个文件避免忘记关闭,python一行写的太长,怎么编写多行的规范
- php-判断一个文件是否存在,便于删除等操作
- "某个程序安装已在安装计算机上创建挂起的文件操作" 解决办法
- C语言一个关于文件操作的示例
- 一个用 C# 实现操作 XML 文件的公共类代码
- 在文档库或 Windows SharePoint Services SharePoint Portal Server 中创建一个新的文件夹或新文档时,您会收到一个"指定的文件或文件夹名太长"错误消息
- java文件操作的一个小实例
- Delphi 文件的操作:重命名、复制、移动、删除(制作一个信息上传控件)
- Access中"操作必须使用一个可更新的查询"错误的解决办法
- VS2005发布网站问题及"aspnet_merge.exe”已退出,代码为 1的错误以及所有代码文件生成一个dll
- 文件操作:洗牌/统计文本文件单词/复制mp3文件/多个文件合并成一个文件
- python按行读取文件 如何去掉换行符 "\n"
- ubuntu ll命令 文件之后带一个星号"*"的含义
- 递归遍历一个文件夹,对文件进行操作,使用lstat时的悲剧
- 一天一个shell命令 linux文件操作系列-ln命令详解
- 未能加载文件或程序集"System.Data,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"或它的某一个依赖项。系统找不到指定的文件。解决办法
- 文件过滤驱动--一个Unicode操作的Lib
- asp.net提示"操作必须使用一个可更新的查询"的解决办法