我正在尝试使用std::wifstream和std::getline读取以Shift-JIS(cp 932)编码的文本文件。以下代码在VS2010中有效,但在VS2013中失败:

std::wifstream in;
in.open("data932.txt");

const std::locale locale(".932");

in.imbue(locale);

std::wstring line1, line2;
std::getline(in, line1);
std::getline(in, line2);
const bool good = in.good();

该文件包含几行,第一行仅包含ASCII字符,第二行是日语脚本。因此,在运行此代码段时,line1应该包含ASCII行,line2是日语脚本,good应该为true。

在VS2010中编译时,结果符合预期。但是在VS2013中进行编译时,line1包含ASCII行,但是line2为空,而good为false。

我调试了CRT(由于Visual Studio提供了源代码),发现在这两个版本之间修改了一个名为_Mbrtowc的内部函数(在xmbtowc.c文件中),以及它们用来检测前导字节的方式。更改了一个双字节字符,并且VS 2013中的一个字符无法检测到前导字节,因此无法解码字节流。

进一步的调试揭示了一个问题,即在其中初始化了_Cvtvec对象的_Isleadbyte数组(在函数xwctomb.c中的_Getcvt()函数中),并且该初始化产生了错误的结果。似乎它总是使用代码页1252(这是我的系统上的默认代码页),而不是为正在使用的流设置的932。但是,我无法确定是否是设计使然,我错过了一些获得良好效果的必要步骤,或者这确实是VS2013的CRT中的错误。

不幸的是我没有安装VS2012,因此无法在该版本上进行测试。

欢迎对此主题有任何见解!

最佳答案

我找到了一种解决方法:如果为了创建语言环境,我明确地更改了全局MBC代码页,则语言环境正确初始化,并且按预期方式读取和解码了行。

const int oldMbcp = _getmbcp();
_setmbcp(932);
const std::locale locale("Japanese_Japan.932");
_setmbcp(oldMbcp);

07-28 03:21
查看更多