C++读UNICODE文本

来源:互联网 发布:淘宝客佣金代扣款 编辑:程序博客网 时间:2024/05/17 01:09

熟悉一下字符类型,char, wchar_t, tchar,最熟悉的char是单字节字符,适用于ansi编码;wchar_t

 

是双字节的宽字符类型,适用于unicode编码;tchar是一个宏,在ansi坏境下定义为char,unicode

 

坏境下定义为wchar_t。

 

怎么来表示字符串?对,字符数组,要知道在c++语言里面,其实没有数组的数据结构,所谓数组,都

 

是由指针+长度来表示。字符型指针const char *, const wchar_t *, const tchar *可以用来在不同的环

 

境下表示字符串。再说相关的几个宏,lpstr: long point string, 相当于char *; lpcstr: long point

 

const string, 相当于 const char *; lpcwstr: long point const wide string, 相当于 const wchar_t *;

和 "用c++读写unicode文本" 有关的c#、asp.net、c++编程小帖士:

strong>DOC对象.CreateElement("新建节点名"); 

创建XML文档新节点 

lpctstr: 类似的,相当于 const tchar *; 这些都不要死记硬背,记着大写字母的意思即可猜出其含义

 

 

一个字符串,比如说"北京2008",对应ansi编码表示为 const char * cha = "北京2008"; unicode编码

 

表示为 const wchar_t * wcha = l"北京2008"; 。在内存里以二进制存储,ansi编码对应为 0x b1b1

 

bea9 32 30 30 38,unicode编码为 0x 1753 ac4e 3200 3000 3000 3800。

 

回到上面,为什么字符型指针可以表示一个字符串?计算机找到这个指针,只能知道串首字符,这里因

 

为字符串有个默认的结束符'/0'(ansi或者ascii表示为0x00),从首字符开始,计算机开始向后查找直

 

到0x00,认为字符串结束,所以存储字符串的时候,计算机是带着一个特殊结束符的。可是要注意了,

 

这个结束符0x00是ascii码定义的结束符啊,那么在宽字符unicode环境下呢?结束符是什么?是

 

0x0000。

 

而对于非const字符串,怎么表示?char * 方法怎么动态定义长度?好办,可以用new手动分配内存空间

 

,除此之外,还有更好办的方法,那就是字符串类型string, 怎么可变长度,怎么记录长度,内存怎么存

 

储,这些都不用管,都有c++标准库自动管理。

 

不同类型的字符串间之间怎么转换?比如定义 char * cha; string str; str = cha; // 可以实现 char * 到

 

string 的转换, cha = str.c_str(); 可以从 string 转换到 char *;对于wchar_t wcha; wstring wstr; 呢

 

?wstr = wcha; wcha = wstr.c_str(); // 这个是否可以呢?!

 

说过了字符串的表示和类型转换,再来看字符流i/o,c++里面的fstream, ifstream, ofstream, 文件流

 

的i/o有好多种方式,默认为字符流方式,明确的说是ansi字符流,都是针对ansi文本的,那么

 

unicode怎么读写呢?

 

c++里倒真有wfsteam流的,可惜用起来也很奇怪,用wifstream读取unicode文本,结果竟然是读取一

 

个字节,加上一个0x00,在读取下一个字节,如此!比如文本里保存的还是“北京2008”,刚才说过

 

unicode编码为 0x 1753 ac4e 3200 3000 3000 3800;用wifstream读到内存的字符竟是 0x 1700

 

5300 ac00 4e00 ... 这叫什么unicode?我不知道wfstream怎么正确使用用,有知道的朋友还请不吝告

 

知!

 

既然wftream不行,那么怎么读取unicode呢,这里可以借鉴一下二进制流的读写方式,二进制流在读写

 

时必须明白存储单位的数据结构,定义为结构体,然后逐n字节(n为结构长度)按二进制读取;这个可

 

以借鉴过来,不用定义结构了,直接用wchar_t,代码如下:
ifstream fin;
fin.open(filename, ios::binary);
// 跳过unicode文本开头有两个字节0xfffe(称作bom,用于标识unicode编码)
fin.seek(2, ios::beg);
while (!fin.eof())
{
wchar_t wch;
fin.read((char *)(&wch), 2);
}

 

如果要按行读取,怎么办?好了,有ifstream的成员函数getline(cha, size),还有string类成员函数

 

getline(fin, str)。你试试能不能用在unicode下使用?答案是否定的!为什么?因为getline函数默认在

 

ansi下使用,它对换行符的判断是基于ascii码的换行(0x0d)和行开头标记(0x0a),如果把它用在

 

unicode编码下,比如“不”字,unicode编码为0x0d4e。当getline函数执行到这,以为换行了,所以

 

说会失效!那么unicode换行符以及行开头符的二进制是什么?双字节了,是0x0d00和0x0a00,这时候

 

getline函数就失效了,怎么办,手动判断:
ifstream fin;
fin.open(filename, ios::binary);
size_t index = 2;
while (!fin.eof())
{
fin.seekg(index, ios::beg);
wchar_t wch;
fin.read((char *)(&wch), 2);
if (wch == 0x000d) // 判断回车
{
strlineansi = ws2s(wstrline);
wstrline.erase(0, wstrline.size() + 1);
iline++;
index += 4; // 跳过回车符和行开头符
}
else
{
wstrline.append(1, wch);
index += 2;
}
}

 

上面的程序可以读取unicode了,那么读了进来怎么理解unicode呢,这就需要char * 和 wchar_t *间的

 

转换了,这个没有简便的方法,ansi、unicode两种编码之间的转换,只能靠查表实现,c++提供了

 

两个函数,wcstombs(_dest, _source, _dsize) 从unicode编码转化为ansi编码 ,mbstowcs(_dest,

 

_source, _dsize)反之,参数对应为const char*, const wchar_t*以及长度。这里在提供一个网上的函数

 

,用于实现string和wstring的转换:
std::string ws2s(const std::wstring& ws)
{
std::string curlocale = setlocale(lc_all, null); // curlocale = "c";
setlocale(lc_all, "chs");
const wchar_t* _source = ws.c_str();
size_t _dsize = 2 * ws.size() + 1;
char *_dest = new char[_dsize];
memset(_dest,0,_dsize);
wcstombs(_dest,_source,_dsize);
std::string result = _dest;
delete []_dest;
setlocale(lc_all, curlocale.c_str());
return result;
}

 

std::wstring s2ws(const std::string& s)
{
setlocale(lc_all, "chs");
const char* _source = s.c_str();
size_t _dsize = s.size() + 1;
wchar_t *_dest = new wchar_t[_dsize];
wmemset(_dest, 0, _dsize);
mbstowcs(_dest,_source,_dsize);
std::wstring result = _dest;
delete []_dest;
setlocale(lc_all, "c");
return result;
}

 

写到这里,就可以用c++读取unicode文本了,写的方法类似。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 法院执法局执法不公怎么办 搞养殖卖不出去怎么办 孔雀吃了蚯蚓该怎么办 多肉幼苗长徒了怎么办 小鸵鸟嘴断了怎么办 武汉早谢怎么办博大直上 威猛先生伤手了怎么办 嗓子眼边条线下边长块肉怎么办 线长在肉里怎么办 北京买车没有号怎么办 租的车处理违章怎么办 以租代购车不要怎么办 订车的合同掉了怎么办 买车合同丢了怎么办 车的证件都丢了怎么办 桃树直立的徒长枝怎么办 月季花长了独枝怎么办? 6岁半B超没子宫怎么办 学生学籍号和身份证号不一致怎么办 学生学籍号和身份证号不一样怎么办 领导交代的任务完不成怎么办 洗衣机里的衣服有味道怎么办 新买的洗衣机有味道怎么办 模拟工业装置没有数据验证怎么办 民办学校的指标生学费怎么办 孩子上初中后成绩不好怎么办 孩子考最后一名怎么办 数学大题不会做怎么办 小学六年级数学考30分怎么办 六年级数学考了30分怎么办 数学考了30分怎么办 没有给直接领导报到怎么办 小学二年级成绩不好怎么办 初中孩子上课注意力不集中怎么办 学生打架家长争吵老师怎么办 我和我老婆感情危机怎么办 数学作业做得慢怎么办 待转弯区变红灯怎么办 大班健康发生火灾怎么办教案 数字化审图图纸提交不了怎么办 监狱建筑师没电了怎么办