2009-08-13 13 views
12

Kiedy czytam plik tekstowy do szerokiego łańcucha znaków (std :: wstring) przy użyciu Wifstream, czy implementacja strumienia obsługuje różne kodowania - to znaczy może być wykorzystana do odczytu np. Pliki ASCII, UTF-8 i UTF-16?ma (w) ifstream obsługuje różne kodowania

Jeśli nie, co powinienem zrobić?

(I trzeba czytać całego pliku, jeżeli to robi różnicę)

+2

jak zaimportować strumienie z ustawieniami regionalnymi. http://stackoverflow.com/questions/207662/writing-utf16-to-file-in-binary-mode/208431#208431 –

Odpowiedz

21

C++ obsługuje kodowanie znaków za pomocą std::locale i aspektu std::codecvt. Ogólną ideą jest to, że obiekt locale opisuje aspekty systemu, które mogą różnić się w zależności od kultury, języka (człowieka) do języka. Aspekty te są podzielone na facet s, które są argumentami szablonu, które definiują sposób konstruowania obiektów zależnych od lokalizacji (włącznie ze strumieniami We/Wy). Po przeczytaniu z istream lub zapisaniu do ostream, rzeczywiste zapisywanie każdego znaku jest filtrowane poprzez fasety ustawień narodowych. Fasety obejmują nie tylko kodowanie znaków Unicode, ale także różne funkcje, takie jak zapisywanie dużych liczb (na przykład przecinkami lub kropkami), waluty, czasu, wielkich liter i mnóstwa innych szczegółów.

Jednak tylko dlatego, że istnieją urządzenia do kodowania, nie oznacza to, że biblioteka standardowa obsługuje wszystkie kodowania, ani nie czyni tego kodu prostym do zrobienia. Nawet takie podstawowe rzeczy, jak rozmiar postaci, którą powinieneś czytać (nie mówiąc już o kodowaniu) są trudne, ponieważ wchar_t może być zbyt mały (zniekształcanie danych) lub zbyt duży (marnowanie miejsca) i najbardziej powszechne kompilatory (np. Visual C++ i Gnu C++) do różnią się tym, jak duża jest ich implementacja. Więc zazwyczaj musisz znaleźć zewnętrzne biblioteki, aby wykonać faktyczne kodowanie.

  • iconv jest ogólnie uznawany za poprawny, ale trudno znaleźć przykłady tego, jak powiązać go z mechanizmem C++.
  • jla3ep mentionslibICU, która jest bardzo dokładna, ale C++ API nie próbuje grać ładnie ze standardem (o ile mogę powiedzieć. Można skanować examples aby sprawdzić, czy można to zrobić lepiej)

Najprostszym przykładem, jaki mogę znaleźć, obejmującym wszystkie bazy, jest Boost UTF-8 codecvt facet, z przykładem, który w szczególności próbuje kodować UTF-8 (UCS4) do użytku przez strumienie IO. Wygląda na to, chociaż nie sugeruję po prostu skopiować go dosłownie. To zajmuje trochę więcej kopanie w the source go zrozumieć (i nie mam zastrzeżeń do):

typedef wchar_t ucs4_t; 

std::locale old_locale; 
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>); 

... 

std::wifstream input_file("data.utf8"); 
input_file.imbue(utf8_locale); 
ucs4_t item = 0; 
while (ifs >> item) { ... } 

Aby zrozumieć więcej o lokalizacjach, oraz sposób ich używać aspekty (w tym codecvt), przyjrzeć się następujące :

+1

Ładne podsumowanie. Możesz dodać http://www.amazon.com/dp/0201183951 do swojej listy książek. To najdokładniejsze podejście do problemu, jaki znam. – sbi

+0

sbi: Dodano książkę do listy. Dzięki za fajny link. – quark

4

ifstream nie dba o kodowanie pliku. Po prostu odczytuje znaki (bajty) z pliku. wifstream czyta szerokie bajty (wchar_t), ale nadal nie wie nic o kodowaniu plików. wifstream jest wystarczająco dobry dla UCS-2 - kodowanie znaków o stałej długości dla Unicode (każdy znak jest reprezentowany dwoma bajtami).

Można użyć biblioteki IBM ICU do obsługi plików Unicode.

Międzynarodowy Komponent dla Unicode (ICU) jest dojrzałym, przenośny zestaw C/C++ i biblioteki Java dla wsparcia Unicode, internacjonalizacji Oprogramowanie (i18n) i globalizacji (G11N), dzięki czemu aplikacje te same wyniki na wszystkich platformach .

ICU jest wydana na podstawie nieograniczonej licencji typu open source, która jest odpowiednia do użytku zarówno z komercyjnym oprogramowaniem, jak iz innym oprogramowaniem typu open source lub bezpłatnym.

+1

Myślę, że nieco bardziej poprawne jest mówienie o abstrakcjach "ifstream" nad kodowaniem. Korzysta z niego dzięki urządzeniom niższego poziomu: locale (dla standardowego C++) i funkcje specyficzne dla systemu operacyjnego lub biblioteki i18n. np. 'ifstream' może nie obchodzić, ale w tym przypadku obchodzi cię to, co wywołuje. – quark

+3

'locales' nie ma nic wspólnego z kodowaniem Unicode. Kiedy ustawiasz ustawienia narodowe, po prostu podpowiadasz 'iostream', w jaki sposób powinien reprezentować symbole na konsoli. Ale nie można wykryć kodowania pliku *. I nie można odróżnić ANSI od UTF-8 za pomocą 'ifstream'. –

Powiązane problemy