Pytanie w sprawie fstream, c++, unicode, utf-8, windows – fstream :: open () Znaki Unicode lub Non-Ascii nie działają (z std :: ios :: out) w systemie Windows

3

W projekcie C ++ chcę otworzyć plik (fstream::open()) (co wydaje się poważnym problemem). Kompilacja mojego programu w systemie Windows kończy się niepowodzeniem.

Plik „ä” (UTF-8 0xC3 0xA4)

<code>std::string s = ...;
//Convert s
std::fstream f;
f.open(s.c_str(), std::ios::binary | std::ios::in); //Works (f.is_open() == true)
f.close();
f.open(s.c_str(), std::ios::binary | std::ios::in | std::ios::out); //Doesn't work
</code>

Ciągs jest kodowany w UTF-8, ale następnie konwertowany z UTF-8 na Latin1 (0xE4). Używam Qt, więcQString::fromUtf8(s.c_str()).toLocal8Bit().constData().

Dlaczego mogę otworzyć plik do czytania, ale nie do pisania?

Plik „и” (UTF-8 0xD0 0xB8)

Ten sam kod w ogóle nie działa.

Wygląda na to, że ta postać nie pasuje do zestawu znaków Windows-1252. Jak mogę otworzyć taki strumień (nie używam MSVC, więcNiefstream::open(const wchar_t*, ios_base::openmode))?

Twoja standardowa biblioteka C i C ++ musi obsługiwać Unicode (tzn. Musi konwertować swoje ciągi wejściowe UTF-8 na UTF-16, a następnie wywołaćCreateFileW). Jeśli tego nie zrobią, stracisz szczęście - prawdopodobnie będziesz musiał zadzwonićCreateFileW bezpośrednio. Philipp
Długa odpowiedź na krótki komentarz: patrzutf8everywhere.org o tym, jak to zrobić dobrze. Pavel Radzivilovsky
@ basic6: Niestety nie wiem, czy istnieje sposób, aby to zrobić. Jeststd::wfstream klasa, ale jejopen metoda również zajmuje tylkoconst char* dla nazwy pliku. Jeśli chcesz mieć możliwość otwierania nazw plików Unicode, musisz albo użyć biblioteki stdio C, albo w pełni buforować dane pliku, odczytując je w pamięci i używającstd::stringstream analizować dane. Adam Rosenfield
@Adam Rosenfield Używam mingw32-g ++ - 4.6.2. _wfopen () zwraca wskaźnik FILE *, jak mogę w ten sposób otworzyć obiekt Fstream? basic6

Twoja odpowiedź

2   odpowiedź
3

: fstream) w systemie Windows, możesz otworzyć plik tylko wtedy, gdy nazwa pliku może być zakodowana przy użyciu aktualnie ustawionej „strony kodowej ANSI” (CP_ACP).

Oznacza to, że mogą istnieć pliki, których po prostu nie można otworzyć za pomocą tych interfejsów API w systemie Windows. O ile Microsoft nie wdroży obsługi ustawiania CP_ACP na CP_UTF8, nie może to być użycie standardowej implementacji biblioteki Microsoft CRT lub C ++.

(Windows ma funkcję zwaną „krótkimi” nazwami plików, gdzie po włączeniu każdy plik na dysku ma nazwę pliku ASCII, która może być używana za pośrednictwem standardowych interfejsów API, jednak ta funkcja nie działa, więc nie stanowi realnego rozwiązania).

3

enie (przeciążenie), które umożliwia obsługę Unicode ciągów kodowanych w UTF-16.

Po prostu przekaż kodowanie std :: wstring UTF-16 do fstream :: open (). To jedyny sposób, aby działał z Fstream.

Możesz przeczytać więcej na temat tego, co uważam za najłatwiejszy sposób na obsługę Unicode tutaj:http://utf8everywhere.org/

@ basic6: przeczytajelementy konwersji Sekcja. AFAIK biblioteka nowidów powinna również działać na MinGW. ybungalobill
Prawdopodobnie jest to odpowiednie rozwiązanie, ale AFAIK to przeciążenie jest dostępne tylko z MSVC, a nie z MinGW („brak funkcji dopasowania do wywołania ...”). I nie używam kompilatora Microsoftu, ponieważ nie przeportowałem kodu, nad którym obecnie pracuję, na C ++ Microsoftu (innymi słowy, kod nie będzie się kompilował i jeszcze się nie zastanawiałem, dlaczego). basic6

Powiązane pytania