VC++读写文件
目录
第1章读写文件
1.1 API
使用VC++读写文件,最直接、最高效的方法就是使用 Windows API,如:使用 CreateFile 打开文件,使用 WriteFile 写文件,使用 ReadFile 读文件……Windows 平台下,所有对文件的读写操作,最终都会调用这些 API 函数。使用 API 的效率最高,对文件读写的控制最强,缺点就是比较复杂,而且代码没有可移植性。
1.2 低级IO
为了方便移植 UNIX 的C代码,VC++的C运行时库实现了一套低级IO函数,如:_open、_write、_read……
1.2.1 文件序号
_open返回的是一个整数,MSDN上称其为文件句柄(file handle),这与CreateFile返回的文件句柄容易混淆。为此,本文称_open返回的为文件序号。
VC++中,系统预先打开了三个文件,其文件序号如下表所示
|
流 |
文件序号 |
说明 |
|
stdin |
0 |
标准输入设备,一般就是键盘 |
|
stdout |
1 |
标准输出设备,一般就是控制台 |
|
stderr |
2 |
标准错误输出设备,一般就是控制台 |
也就是说,无需调用_open,可以直接调用_write(1,"abc",3);往控制台输出abc三个字符。
1.2.2 文本文件与二进制文件
读写二进制文件时,不会做任何处理,数据保持原样。写文本文件时,VC++会将换行符(即\n,0AH)替换为回车(即\r,0DH)和换行符;读文本文件时,VC++会将\r\n替换为\n,并且在读取到1AH时,认为文件结束。
_open函数里可以指定文件模式,
如:_open("c:\\1.txt",_O_RDONLY | _O_TEXT); //文本模式
如:_open("c:\\1.txt",_O_RDONLY | _O_BINARY); //二进制模式
如果_open函数里未指定 _O_TEXT 和 _O_BINARY,则以全局变量_fmode为准,如下面的代码将以文本模式打开文件。
_fmode = _O_TEXT;
_open("c:\\1.txt",_O_RDONLY);
假定c:\1.txt的内容如下:
|
1 |
2 |
3 |
\r |
\n |
4 |
5 |
6 |
\r |
\n |
执行如下代码:
|
int n = _open("c:\\1.txt",_O_RDONLY | _O_BINARY); char str[128]; _read(n,str,128); _close(n); |
str的内容将是"123\r\n456\r\n"。将_O_BINARY替换为_O_TEXT,则str的内容将变为"123\n456\n"。可见\r\n如期的被替换为\n。不过,需要注意的是:将\r\n替换为\n是在第二个参数内进行的,如:将_read(n,str,128);替换为下面两行代码:
_read(n,str,4); //读取到"123\r"
_read(n,str,4); //读取到"\n456"
这个时候,\r\n就不会被替换为\n。这点要特别注意。
1.3 流IO
流IO函数有:fopen、fwrite、fread……它与低级IO最大的区别在于:低级IO无缓冲区,而流IO有缓冲区。如:同样的写文件,_write 会直接调用 WriteFile,而 fwrite 会将数据写入缓冲区,达到一定数量后,再调用 WriteFile 将缓冲区内的数据写入文件。显然,流IO将大大减少调用 API 函数的次数,因此理论上其效率会比较高。
使用setvbuf函数,可以对缓冲区的大小、行为进行设置。
VC++里,流IO由低级IO实现。即:fopen会调用_open,fwrite会调用_write,fgets会调用_read函数……
流IO最重大的意义在于:它是符合ANSI C 标准的一套函数,可移植性最高。
1.4 Unicode
Windows的API函数一般会分为两个版本,即处理ANSI字符串的窄字符版本,和处理Unicode字符串的宽字符版本。低级IO和流IO也有类似的宽字符版本函数,如:_wopen、_wfopen……
使用宽字符版本的IO函数之前,一定要调用setlocale(LC_ALL,""),设置 C 函数的代码页为系统默认的代码页,否则就有可能会出现乱码。
1.5 流IO、低级IO、API之间的关系
三者的关系如下图所示:流IO由低级IO实现,而低级IO由API实现。

函数_fileno可根据流IO的FILE*获得低级IO的文件序号;
函数_get_osfhandle可根据低级IO的文件序号获得API的文件句柄;
函数_open_osfhandle可根据API的文件句柄获得低级IO的文件序号;
函数_fdopen可根据低级IO的文件序号获得流IO的FILE*。
1.6 随机读写
随机读写是对文件读写的一种方式,具体表现为:
1、读或写时,会移动文件指针;
2、读、写操作交叉进行,如:读了几次后又写几次。
如果使用低级IO进行随机读写,读写函数的处理是比较简单的。反之,对于有缓冲区的流IO而言,随机读写反而可能会降低文件的读写效率。因为以上两个操作,将频繁的清空缓冲区、移动文件指针。可以说,在随机读写文件上,流IO并不比低级IO有优势。
1.7 C++IO流
C++的STL中,可以使用 fstream、ifstream、ofstream……对文件进行读写。它的内部使用了流IO。
1.8 MFC
1.8.1 CFile
CFile是低级IO的C++实现。它直接调用 API,主要用于读写二进制文件。
1.8.2 CStdioFile
CStdioFile用于读写文本文件,具体的就是读写一行行的文本。它内部调用了流IO。当以 Unicode 编译程序时,CStdioFile 将调用 Unicode 版本的流IO函数,此时一定要首先调用 setlocale(LC_ALL,"")。还需要说明的一点是:从 EVC3.0 至 VC2008,CStdioFile 都是无法正常运行在 Windows CE 平台上的。
1.8.3 CArchive
CArchive 主要用于串行化,它可以与 CFile 或 CMemFile 关联,然后通过<<和>>方便的实现变量的串行化和反串行化。
CArchive 与 CFile 关联,串行化时变量将保存至文件。
CArchive 与 CMemFile 关联,串行化时变量将保存至内存。
CArchive 与CSocketFile关联,串行化时变量将通过套接字传输到网络。
1.9 总结
如果使用C语言,可以选择使用API、低级IO、流IO。如果代码要移植到其它平台,建议使用流IO。如果使用C++语言,上述方法均可使用。
读写二进制文件相对比较容易,比较复杂的是读写文本文件。复杂在两个方面:
1、各个操作系统定义的行结束符不尽相同,如:Linux定义\r为行结束符,Mac定义\n为行结束符,Windows定义\r\n为行结束符。而且,还需要考虑各个操作系统之间的文件读写,如:Linux生成的文本文件在Windows下读取……
2、必须考虑多种编码。如:Windows平台下,文本文件分为四种格式:ANSI、UTF16LE、UTF16BE、UTF-8。VC++6.0只支持读写ANSI编码的文本文件。自VC++2005开始,fopen增加了对UTF16LE、UTF-8这两种编码的支持,不过这种支持不适用于 Windows CE 平台。
上述两个问题,最好的解决办法就是自行编写一个处理文本文件的C++类。
VC++读写文件的更多相关文章
- VC的文件操作
各种关于文件的操作在程序设计中是十分常见,如果能对其各种操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而在较短的时间内编写出高效的代码,因而熟练的掌握文件操作是十分重要的.本文将对Visua ...
- Hyper-V无法文件拖拽解决方案~~~这次用一个取巧的方法架设一个FTP来访问某个磁盘,并方便的读写文件
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 服务器相关的知识点:http://www.cnblogs.com/dunitia ...
- 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库
57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...
- Python读写文件
Python读写文件1.open使用open打开文件后一定要记得调用文件对象的close()方法.比如可以用try/finally语句来确保最后能关闭文件. file_object = open('t ...
- php中并发读写文件冲突的解决方案
在这里提供4种高并发读写文件的方案,各有优点,可以根据自己的情况解决php并发读写文件冲突的问题. 对于日IP不高或者说并发数不是很大的应用,一般不用考虑这些!用一般的文件操作方法完全没有问题.但如果 ...
- C#读写文件的方法汇总_C#教程_脚本之家
C#读写文件的方法汇总_C#教程_脚本之家 http://www.jb51.net/article/34936.htm
- Inno Setup 如何读写文件
软件安装的实质就是拷贝,对于简单的打包当然不需要考虑修改某(配置)文件.通过inno修改文件的目的在于把安装时相关信息写入文件中,提供其它应用的读取,而这些信息也只能在安装时才能确定,比如安装用户选择 ...
- java使用IO读写文件总结
每次用到IO的读写文件都老忘记写法,都要翻过往笔记,今天总结下,省的以后老忘.java读写文件的IO流分两大类,字节流和字符流,基类分别是字符:Reader和Writer:字节:InputStream ...
- python读写文件时中文的转码问题
读写文件都要将中文转为unicode字符. 读文件: u = unicode(s, 'gbk') 这里不能使用encode 写文件: u = encode('utf')
随机推荐
- Mac 快速修改 hosts 文件
sudo /Applications/TextEdit.app/Contents/MacOS/TextEdit /etc/hosts
- Laravel 中视图中使用PHP代码
{{ $name }}{{ date('Y-m-d H:i:s',time()) }}{{ in_array($name,$arr)?'true':'false' }} {{ isset($name) ...
- Day 11 正则表达式
正则表达式 一.简介 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配到的行打印出来.grep全称是Globally search for a Regular ...
- ZJGSU-ACM OJ 心得
一个我觉得蛮重要的问题,也是会经常碰到的问题 就是觉得自己对的代码提交到OJ发现输出超限 我是真的输出超限了吗? QAQ 其实,不然. 我把这类问题分为几类: (一):死循环:while(1) 比如以 ...
- PYTHON 源码
http://www.wklken.me/index2.html http://blog.csdn.net/dbzhang800/article/details/6683440
- BUPT复试专题—网络的核(2014)
题目描述 给定一个无向网络G,共有N个节点(1到N),M条边,求网络的核. 网络的核:到网络中其他节点距离之和最小的节点,且对于不连通的两点,他们之间的距离为N,若有多组解,输出编号最小的节点 输入 ...
- 写2个线程,其中一个线程打印1~52,另一个线程打印A~z,打印顺序应该是12A34B45C……5152Z
我写的 class LN { private int flag = 0; public static char ch = 'A'; public static int n = 1; public sy ...
- eclipse新建android项目出现非常多错误
如图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSGFycnlXZWFzbGV5/font/5a6L5L2T/fontsize/400/fil ...
- sed 常用命令
删除以ifeq开头的行 sed -i "/^ifeq/d" file 删除空行 sed -i '/^$/d' file
- 如何删除ini文件中的内容
1.删除子项值:::WritePrivateProfileString(分区名称, 子项名称, "", ini文件路径); 2.删除子项(名称和值):::WritePrivateP ...