2014-10-28 8 views
5

Próbuję odczytać plik tekstowy zakodowany w Shift-JIS (cp 932) przy użyciu std :: wifstream i std :: getline. Poniższy kod działa w VS2010, ale nie w VS2013:Dekodowanie Shift-JIS nie działa przy użyciu wifstrem w Visual C++ 2013

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(); 

Plik zawiera kilka linii, gdzie pierwsza linia zawiera tylko znaki ASCII, a drugi to japoński scenariusz. Tak więc, po uruchomieniu tego fragmentu, line1 powinien zawierać wiersz ASCII, line2 skrypt japoński, a good powinien być prawdziwy.

Po kompilacji w VS2010 wynik jest zgodny z oczekiwaniami. Ale po kompilacji w VS2013, line1 zawiera linię ASCII, ale line2 jest pusta, a good jest fałszywa.

Po debugowaniu do CRT (jako źródło dostarczono Visual Studio) i odkryłem, że wewnętrzna funkcja o nazwie _Mbrtowc (w pliku xmbtowc.c) została zmodyfikowana między dwiema wersjami i sposób, w jaki używają do wykrywania zmieniono bajt wiodący znaku dwubajtowego, a ten w VS 2013 nie wykrył bajtu wiodącego, a zatem nie dekoduje strumienia bajtów.

Dalsze debugowania wykazała punktu, w którym _Isleadbyte tablicy A _Cvtvec obiektu jest inicjowany (w funkcji _Getcvt() w pliku xwctomb.c) oraz że inicjalizacja wytwarza błędny wynik. Wydaje się, że zawsze używa strony kodowej 1252, która jest domyślną stroną kodową w moim systemie, a nie 932, która jest ustawiona dla używanego strumienia. Jednak nie mogłem zdecydować, czy jest to zgodne z projektem, i brakowało mi pewnych wymaganych kroków, aby uzyskać dobry wynik, lub jest to rzeczywiście błąd w CRT dla VS2013.

Niestety nie mam zainstalowanego VS2012, więc nie mogłem przetestować tej wersji.

Wszelkie spostrzeżenia na ten temat są mile widziane!

+0

post to connect.microsoft.com –

+0

Chciałbym zacząć od próby 'nasycić()' nowego lokum przed otwarciem pliku: Myślę, że strumień może odczytać znaki podczas gdy otwarta i znaki są czytane nie zmieni on używanego aspektu 'std :: codecvt <...>'. –

+0

@ DietmarKühl Właśnie sprawdziłem, ale wyniki były takie same: działa w VS2010, ale nie działa tak samo w VS2013. –

Odpowiedz

2

Znalazłem obejście: jeśli do utworzenia ustawień narodowych wyraźnie zmieniam stronę globalnego kodu MBC, ustawienia regionalne są poprawnie inicjowane, a linie są odczytywane i dekodowane zgodnie z oczekiwaniami.

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

Ale jak to wydaje się być tylko obejściem, nie przyjmuję go jako odpowiedzi ... –

+0

Byłem [hit] (http://stackoverflow.com/questions/33254089/double-byte-character-sequence-conversion-issue -in-visual-studio-2015) również. Wypełniłem [zgłoszenie błędu] (https://connect.microsoft.com/VisualStudio/feedback/details/1925650) w związku z tym problemem. – wilx

Powiązane problemy