在Visual C++2013中使用wifstrem进行Shift JIS解码失败

Shift-JIS decoding fails using wifstrem in Visual C++ 2013

本文关键字:Shift 进行 JIS 解码 失败 wifstrem Visual C++2013      更新时间:2023-10-16

我正在尝试使用std::wifstream和std::getline读取以Shift-JIS(cp932)编码的文本文件。以下代码在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数组被初始化(在函数_Getcvt()中,在文件xwctomph.c中),并且初始化会产生错误的结果。它似乎总是使用代码页1252,这是我系统上的默认代码页,而不是为正在使用的流设置的932。然而,我无法决定它是否是设计的,我错过了获得好结果所需的一些步骤,或者这确实是VS2013 CRT中的一个错误。

不幸的是,我没有安装VS2012,所以我无法在那个版本上进行测试。

欢迎对这个话题有任何见解!

我找到了一个解决方法:如果为了创建区域设置,我显式地更改全局MBC代码页,则区域设置将正确初始化,并且行将按预期读取和解码。

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