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?
Odpowiedz
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.
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) –
Hmm, wygląda na to, że masz rację . Poprawiłem: – jalf
@ É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
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.
Czy to będzie ostatecznie/teoretycznie przenośne? –
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. –
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
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.
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". –
Chodziło mi o to, że akceptują ciągi Unicode, które odpowiadają na pytanie, czyż nie? – Brackets
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). –
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;
}
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. –
Dlaczego nie używasz typów danych, takich jak 'std :: wofstream'? Zwróć uwagę na ** w **! – sergiol