2009-05-04 9 views
42

Nie można sobie wyobrazić czegoś tak podstawowego, jak otwarcie pliku przy użyciu standardowej biblioteki C++ dla aplikacji Windows było trudne ... ale wygląda na to, że jest. Według Unicode mam na myśli UTF-8, ale mogę przekonwertować na UTF-16 lub cokolwiek innego, chodzi o to, aby uzyskać instancję od nazwy pliku Unicode. Zanim zhackuję własne rozwiązanie, czy jest tu preferowana trasa? Zwłaszcza wieloplatformowy?Jak otworzyć std :: fstream (ofstream lub ifstream) z nazwą pliku Unicode?

+0

I to jest [Duplikat] (http://stackoverflow.com/questions/480849/windows-codepage-interactions-with-standard-cc-filenames) pytanie. Sprawdź, czy którakolwiek z udzielonych odpowiedzi może pomóc. –

+0

Dlaczego nie używasz typów danych, takich jak 'std :: wofstream'? Zwróć uwagę na ** w **! – sergiol

Odpowiedz

51

Standardowa biblioteka C++ nie działa w standardzie Unicode. char i wchar_t nie są wymagane do kodowania Unicode.

W Windows wchar_t jest UTF-16, ale nie ma bezpośredniego wsparcia dla UTF-8 nazw w bibliotece standardowej (the char typ danych nie jest Unicode w systemie Windows)

Z MSVC (a tym samym STL Microsoft) , konstruktor dla filestreams jest warunkiem, który zajmuje const wchar_t* pliku, co pozwala na tworzenie strumienia jak:

wchar_t const name[] = L"filename.txt"; 
std::fstream file(name); 

to jednak przeciążenie nie jest określony przez standard C++ 11 (gwarantuje jedynie obecność char wersja oparta). Nie ma go również w alternatywnych implementacjach STL, takich jak GCC's libstdC++ dla MinGW (-w64), od wersji g ++ 4.8.x.

Należy pamiętać, że podobnie jak char w systemie Windows nie jest UTF8, w innych systemach operacyjnych wchar_t może nie być UTF16. Więc ogólnie rzecz biorąc, nie jest to przenośne. Otwarcie strumienia z nazwą pliku wchar_t nie jest zdefiniowane zgodnie ze standardem, a podanie nazwy pliku w postaci char może być trudne, ponieważ kodowanie używane przez funkcję char różni się między systemami operacyjnymi.

+0

Co masz na myśli mówiąc, że "fstream gwarantuje akceptację obu wchar_t ..."? Nie mam dostępu do oficjalnego standardu 98, ale nie mogę znaleźć wzmianki o wchar_t * ctor dla basic_fstream w n2857 (np. IIUC, aktualny projekt roboczy C++ 0x) –

+0

Hmm, wygląda na to, że masz rację . Poprawiłem: – jalf

+0

@ Éric: agreed, konstruktory dla basic_fstream są zdefiniowane w 27.8.1.12 ze standardu '03 i są dwa: no-args i char *.fstream jest basic_fstream i nie ma żadnych dodatkowych członków zdefiniowanych dla tej specjalizacji. –

3

Obecne wersje Visual C++ std :: basic_fstream mają metodę open(), która przyjmuje wchar_t * zgodnie z http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx.

+0

Czy to będzie ostatecznie/teoretycznie przenośne? –

+3

Nie wszystkie systemy operacyjne i systemy plików obsługują nazwy plików w formacie Unicode, aby nie były przenośne. Z tego, co mogę zebrać, wchar_t * open() i konstruktor na fstream są rozszerzeniami Microsoftu, ponieważ NTFS obsługuje nazwy plików w Unicode. –

+3

lub raczej, ponieważ NTFS używa UTF16 do kodowania nazw plików w Unicode. Linux obsługuje również nazwy plików w Unicode, ale używa UTF8, więc normalna wersja char * działa tam – jalf

1

Użyj std::wofstream, std::wifstream i std::wfstream. Akceptują nazwę pliku Unicode. Nazwa pliku musi być wstring, tablica wchar_t s lub musi mieć makro _T() lub przedrostek L przed tekstem.

+0

Czy możesz podać dowody, że 'std :: wfstream' to' Unicode'? Aż do mojej skromnej wiedzy używają 'wchar_t', która jest szeroką postacią, zwykle' 16-bitową'. Ale treść może być lub nie być "Unicode". –

+0

Chodziło mi o to, że akceptują ciągi Unicode, które odpowiadają na pytanie, czyż nie? – Brackets

+0

Właściwie to odpowiada na połowę pytania: załóżmy, że masz ścieżkę pliku UTF16 w swoim strumieniu wfstream (lub UTF8 w twoim strumieniu). Windows nie akceptuje unicode i zwróci "zły URL", jeśli masz jakieś specjalne znaki (np. Chiński). –

0

Wystarczy popatrzeć na Boost.Nowide:

#include <boost/nowide/fstream.hpp> 
#include <boost/nowide/cout.hpp> 
using boost::nowide::ifstream; 
using boost::nowide::cout; 

// #include <fstream> 
// #include <iostream> 
// using std::ifstream; 
// using std::cout; 

#include <string> 

int main() { 
    ifstream f("UTF-8 (e.g. ß).txt"); 
    std::string line; 
    std::getline(f, line); 
    cout << "UTF-8 content: " << line; 
}