Oto problem, którego nie mogłem rozwiązać pomimo wszystkich moich wysiłków. Więc całkowicie utknąłem, proszę o pomoc!Zły CRLF w strumieniu UTF-16?
Dla normalnego trybu „ASCII” Poniższe uproszczone plików i strumień wyjścia
FILE *fa = fopen("utfOutFA.txt", "w");
fprintf(fa, "Line1\nLine2");
fclose(fa);
ofstream sa("utfOutSA.txt");
sa << "Line1\nLine2";
sa.close();
wynik, oczywiście, dokładnie w tych samych plikach tekstowych (hex zrzutu):
00000000h: 4C 69 6E 65 31 0D 0A 4C 69 6E 65 32 ; Line1..Line2
gdzie nowy linia \n
jest rozszerzana do CRLF: 0D 0A
- typowa dla systemu Windows.
Teraz robimy to samo dla wyjścia Unicode, a konkretnie UTF-16 LE, który jest rodzajem "domyślnym". Plik wyjściowy
FILE *fu = fopen("utfOutFU.txt", "w, ccs=UNICODE");
fwprintf(fu, L"Line1\nLine2");
fclose(fu);
wyniki w tej treści:
00000000h: FF FE 4C 00 69 00 6E 00 65 00 31 00 0D 00 0A 00 ; ÿþL.i.n.e.1.....
00000010h: 4C 00 69 00 6E 00 65 00 32 00 ; L.i.n.e.2.
która wygląda idealnie poprawne rozważa BOM i bajt, włączając CRLF: 0D 00 0A 00
. Jednakże, podobnie wyjściowy strumień
wofstream su("utfOutSU.txt");
su.imbue(locale(locale::empty(), new codecvt_utf16<wchar_t, 0x10ffffUL,
codecvt_mode(generate_header + little_endian)>));
su << L"Line1\nLine2";
su.close();
wyniki w jeden bajt mniej i ogólnie nieprawidłowy plik tekstowy:
00000000h: FF FE 4C 00 69 00 6E 00 65 00 31 00 0D 0A 00 4C ; ÿþL.i.n.e.1....L
00000010h: 00 69 00 6E 00 65 00 32 00 ; .i.n.e.2.
Powodem jest źle ekspansja CRLF: 0D 0A 00
. Czy to błąd? Czy zrobiłem coś złego?
Używam kompilatora Microsoft Visual Studio (14.0 i inne). Próbowałem użyć strumienia endl
zamiast \n
- ten sam wynik! Próbowałem umieścić najpierw su.imbue()
, a następnie su.open()
- wszystko to samo! Ja również sprawdzone wyjście UTF-8 (ccs=UTF-8
do pliku i codecvt_utf8
dla Stream) - nie ma problemu jak CRLF pozostaje taka sama jak w trybie ASCII: 0D 0A
I wdzięczni za wszelkie pomysły i uwagi dotyczące tej kwestii.
Jest to prawdopodobnie błąd, ponieważ koder UTF-16 nie może mieć nieparzystej liczby bajtów. – CAF