设为首页 加入收藏

TOP

用VC++访问文本文件(一)
2014-11-23 21:30:19 】 浏览:992
Tags:访问 文本 文件

初一看这个标题,稍微做过C++编程的人都不认为这是什么困难的事情,但细细想起来还是有些需要注意的。其中我想最主要的就是文本文件的格式了,我们目前常见的有下面这四种,也就是Windows的记事本所能保存的那四种格式了:

\

1,ANSI,也是我们最最常见的文本文件格式,在中文操作系统中,使用默认的GBK编码,而港台用的繁体中文操作系统则默认使用Big5码,简体中文操作系统打开Big5码的文本文件,会显示乱码,反之亦然,ANSI是ASCII的超集,所以英文总是能正常显示,英文占一个字节,中文占两个字节,所以光凭文件大小是不知道字符数的。

2,Unicode(Little endian,LE),这是Windows默认的Unicode编码,每个字符都是占据两个字节,全球统一,所以Unicode编码的文本文件都不会显示乱码,只可能由于缺乏字体的支持而显示出小方块(默认是小方块,也可能是别的)。准确说Unicode的字符并不一定是占据两个字节,但在Windows环境下这么认为是没有任何问题的。

3,Unicode(Big endian,BE),同上,唯一不同的是字节序,貌似这是Mac系统默认的编码格式。比如“中”字的Unicode(LE)编码是“2D 4E”,而Unicode(BE)的编码这是“4E 2D”。

4,UTF-8,和Unicode编码是一一对应的关系,并且兼容ASCII,所以UTF-8编码的文本文件同ANSI编码的那样,英文总是能正常显示,而它每个字符所占据的字节也是不确定的,可能占据一到六个字节,和Unicode不同,UTF-8并没有字节序一说,所以它往往被用作文本传输的标准格式,实现文本的跨平台传输。

别的我知道的还有UTF-16等格式,由于用得少,就不提了。另外,对于以上各类格式,如果有必要,还要区分Windows版,Unix版和Mac版,它们的关键区别在于对换行的理解,Windows版的换行其实是“回车字符”+“换行字符”,也就是0x0D+0x0A,而Unix版的只有“换行符”0x0A,Mac版的只有“回车符”0x0D,真是有趣极了。

那么,当你试图打开一个文本文件的时候,你会以哪种格式去“阅读”它呢?这让我想起以前我曾经工作过的一家公司,把一个任务交给我,就是做文件分类,其中有一个类型就是文本文件,这十分让我头疼,因为文本文件没有固定的格式,所以只好根据一些字符来判断,这个是不一定准的。通常,为了区分文本文件的格式,文本文件编辑器通常都会给文本文件添加一个叫BOM的标志,BOM是Byte Order Marked的缩写:

ANSI:没有BOM,直接是内容。
UNICODE(LE):FF FE
UNICODE(BE):FE FF
UTF-8:EF BB BF

所以我们可以根据这些特征来判断一个文本文件的编码格式。

那如果一个Unicode文件没有BOM,我们把它判定为ANSI格式的,岂不是乱了套?那是肯定的,但有些比较高级的文本编辑器,如UltraEdit,就有智能识别文本格式的功能,即便文本文件缺乏BOM,但这个我们就不讨论了。

也许你要问了:“有那么繁琐么?我只是想用C运行库获取文本内容。”在Windows环境下,目前还算比较简单了,VC++2005的运行库已经支持读取Unicode和UTF-8格式的文本文件,而下面我给出一个简单的例子,是读取一个UTF-8格式的文本文件的。

#include "stdafx.h"
#include <windows.h>

//test_utf8.txt的内容是四个汉字:“中文测试”
//一共占据15个字节,分别是:
//EF BB BF E4 B8 AD E6 96 87 E6 B5 8B E8 AF 95
//其中“EF BB BF”为BOM(Byte Order Mark),之后每个汉字占3个字节
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR szDataAll[64];
FILE* pf = _wfopen(L"test_utf8.txt", L"r,ccs=utf-8");
if (pf!=NULL)
{
long pos = ftell(pf); //3

ZeroMemory(szDataAll, sizeof(szDataAll));
fread(szDataAll, 2, 1, pf);
pos = ftell(pf); //9
OutputDebugStringW(szDataAll); //中

ZeroMemory(szDataAll, sizeof(szDataAll));
fread(szDataAll, 2, 1, pf);
pos = ftell(pf); //11
OutputDebugStringW(szDataAll); //文

ZeroMemory(szDataAll, sizeof(szDataAll));
fread(szDataAll, 2, 1, pf);
pos = ftell(pf); //13
OutputDebugStringW(szDataAll); //测

ZeroMemory(szDataAll, sizeof(szDataAll));
fread(szDataAll, 2, 1, pf);
pos = ftell(pf); //15
OutputDebugStringW(szDataAll); //试

fclose(pf);
}
return 0;
}
需要注意的是,使用fopen的时候,记得使用其宽字符版_wfopen,另外,注意fopen的第二个参数“ccs=utf-8”,是“ccs”而不是“css”,写错的话是无效的,这样就能直接把UTF-8的文本读进来,而不用管BOM,也不需要额外的转换,直接就已经是Unicode编码了。

注意上面我使用了ftell来测试文件指针的位置,看起来文件指针的行为确实有些怪异,貌似ftell使用起来不灵了,这个时候,这是我们要注意的一个地方;另一个要注意的地方就是fread的第二个参数,我写了2,其实指的是读进来的Unicode编码的字节数,要读一个字符,那就写2,读两个字符,那就写4,而不是UTF-8的3个字节一个汉字的这种长度。

如果你要读取一个Unicode(LE)的文本文件,将fopen的“ccs=utf-8”参数改为“ccs=unicode”即可。

这都是你已经知道了文件格式的前提下,所使用的方法,如果文件格式未知,你还得手工判断一下,先用“_wfopen(L"abc.txt", L"rb")”这种方式打开文件,再读取头几个字节来分析。

遗憾的是,“ccs=utf-8”这种参数并不是C的标准,这是Microsoft VC++的功能,并且我发觉Windows Mobile平台不能这样用,so,下面我就只好完全自己动手丰衣足食了,总的思路就是:判断文件格式,根据格式类型和该格式类型的标准,读取一定字符数目(究竟读取多少字节,要计算),然后

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Union和Struct的内存分配 下一篇大端小端存储模式以及其对Union数..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目