windows - UTF8 scrambling under c + + filindlæsning

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg ved, at indlæsning af unicode er et lidt arbejdsområde, men jeg kan ikke se, hvordan man kan anvende de løsninger, der præsenteres for andre for mit særlige problem.


Jeg har et Win7/C ++/DirectX9 GUI bibliotek, der kan gengive tekst til skærmen. Jeg har aldrig haft et problem før, da det kun er brugt med vesteuropæisk sprog. Nu skal jeg bruge det med ungarsk, og det giver mig hovedpine! Mit særlige problem er at indlæse specialtegnene, der findes på dette sprog.


Tag dette eksempel, FELNŐTTEKNEK, der betyder ADULT.


Hvis jeg harddisk kode denne streng i min app, det gør det korrekt:


guiTitle->SetText( L"FELNŐTTEKNEK" );


Dette lagrer strenge som en std :: wstring, hvilket gør det med ID3DXFont :: DrawTextW (). Det beviser også min valgte skrifttype, Futura CE, er i stand til at gengive specialtegnene (CE=Centraleuropæiske).


Så langt så godt. Næste vil jeg simpelthen være i stand til at indlæse teksten fra en tekstfil. Ikke noget særligt. Men resultaterne er dårlige! Den specielle Ő erstattes af et andet tegn, hovedsageligt Å eller endda to tegn som Å (2. et normalt ikke trykt)


Jeg har sikret, at inputtekstfilen er kodet som UTF-8, og jeg forsøger at indlæse det således:


wifstream f("data/language.ini");
wstring w;  
getline( f, w );    
guiTitle->SetText( w );


På en eller anden måde forvrider jeg det stadig. Føjer jeg som UTF-8? Er der en måde at sikre dette på? Jeg skal bare sørge for, at jeg har en bred streng med teksten som vist i teksteditor.


Eventuel bistand modtaget mest taknemmeligt.


Si

Bedste reference


Glem alt om wifstream, det er bare for svært at få det til at fungere. Gør:


ifstream f(L"data/language.ini");
string str;  
getline( f, str );
guiTitle->SetText( utf8\_to\_utf16(str).c\_str() );


Og brug MultiByteToWideChar til at implementere utf8\_to\_utf16.


Se også https://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful.

Andre referencer 1


DrawTextW forventer UTF-16.


Hvad du gør er at konvertere hver UTF-8-kodeenhed (byte) til en 16-bit værdi ved nul padding det - dette konverterer kun UTF-8 til UTF-16, hvis din UTF-8 udelukkende indeholder tegn fra ascii-undersætet af unicode.


Hvad du skal gøre er at konvertere korrekt fra UTF-8 til UTF-16. Indsæt strengen i en std :: streng (ikke en std :: wstring) og konverter derefter den UTF-8-streng til en UTF-16-streng og send den til API'en, der forventer en UTF-16-streng.

Andre referencer 2


Aldrig forstået ideen erklæret der om brugen af ​​UTF-8 overalt, implementering af nødvendige funktioner selv (som du lige så godt kan gøre for UTF-16 også) og derefter konvertere den tilbage til UTF-16, når du kommunikerer med Windows API (og nej idé om, hvordan det skal undgå problemer i Windows API - det giver jo alligevel UTF-16-chars og vil alligevel ramme alle de samme fejl), synes at være en hel del ekstra arbejde uden fordele.


Anyways i stedet for 'use std :: string og derefter konvertere den ved hjælp af lowlevel-metoder til UTF-16', kan du bare lade API'en gøre sit job (Bemærk dette kan ikke resultere i den bedste ydeevne, Ray Chen havde nogle serier om den måde tilbage - selvom jeg håber nyere kompilatorer fikseret det og for en normal fil, der er næppe vigtigt).


Dybest set kan du gøre det:


 std::wifstream src;
 src.imbue(std::locale("UTF-8")); // use correct encoding.
 src.open(file);


Hvorfor gør alt arbejdet selv (og hver gang jeg ikke må bruge MultiByteToWideChar, tæller jeg mig heldig), hvis biblioteket også kan gøre det - gør også hensigten meget klarere.