Декодирование Shift-JIS не удается с помощью wifstrem в Visual C++ 2013

Я пытаюсь прочитать текстовый файл, закодированный в Shift-JIS (cp 932), используя std::wifstream и std::getline. Следующий код работает в 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 должно быть правдой.

При компиляции в VS2010 результат будет таким, как ожидалось. Но при компиляции в VS2013, line1 содержит строку ASCII, но line2 пусто, и good ложно

Я отладил в CRT (так как источник предоставляется в Visual Studio) и обнаружил, что внутренняя функция называется _Mbrtowc (в файле xmbtowc.c) был изменен между двумя версиями, и был изменен способ, который они используют для обнаружения старшего байта двухбайтового символа, а в VS 2013 не удается обнаружить ведущий байт, поэтому не удается декодировать поток байтов.

Дальнейшая отладка выявила точку, где _Cvtvec объекты _Isleadbyte массив инициализируется (в функции _Getcvt()в файле xwctomb.c), и эта инициализация дает неправильный результат. Кажется, что он всегда использует кодовую страницу 1252, которая является кодовой страницей по умолчанию в моей системе, а не 932, которая установлена ​​для используемого потока. Тем не менее, я не мог решить, является ли это разработкой, и я пропустил некоторые необходимые шаги, чтобы получить хороший результат, или это действительно ошибка в CRT для VS2013.

К сожалению, я не установил VS2012, поэтому я не смог протестировать эту версию.

Любые идеи по этой теме приветствуются!

1 ответ

Я нашел обходной путь: если для создания локали я явно изменяю глобальную кодовую страницу MBC, локаль инициализируется правильно, и строки читаются и декодируются, как и ожидалось.

const int oldMbcp = _getmbcp();
_setmbcp(932);
const std::locale locale("Japanese_Japan.932");
_setmbcp(oldMbcp);
Другие вопросы по тегам