今天在写一个小应用的时候,需要从一个UTF-16的文本文件中读入一个一个的宽字符,想当然的以为wifstream天生就能识别 Unicode,代码如下(utf16.txt是一个用记事本编辑并保存为utf16格式的文本文件)
001 wifstream ifs("utf16.txt");
002 for (;;) {
003 wchar_t wc = ifs.get();
004 if (WEOF==wc)
005 break;
006 else
007 cout << wc << ' ';
008 }
...
结果令人失望,ifs >> wc(或ifs.get(wc))只是把文件中的下一个字节置入wc,表现出来的行为与ifstream没有任何区别…& hellip;啊,忘了,utf16的文本文件前面还有两个字节用来标识字节序(在x86平台下,是FF FE,表示低位在前的UTF16),于是在002行前面再加上一句:
ifs.seekg(2, ios::beg);
嗯,BOM(Byte Order Marker)被跳过了,但是get()方法只读一个字节(用>>提取符也是一样)的行为并没有得到改变。不知道wifstream的策略究竟是怎样的(如果wistringstream来测试,行为完全符合预期),为什么会有这种古怪,时间不早,明天来看相关源码,先用其他方法暂时应付过去:
ifstream ifs("utf16.txt", ios::in | ios::binary);
if (!ifs.is_open())
throw runtime_error("open file failed");
ifs.seekg(2, ios::beg);
while (ifs.good()) {
wchar_t wc;
ifs.read((char *)&wc, sizeof(wc));
if (ifs.eof())
break;
else
cout << wc << ' ';
}