Декодирование 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);