Como abrir uma std :: fstream (ofstream ou ifstream) com um nome de arquivo unicode?
Pergunta
Você não poderia imaginar algo tão básico como abrir um arquivo usando a biblioteca C ++ padrão para um aplicativo do Windows foi complicado ... mas parece ser. Por Unicode aqui eu média UTF-8, mas pode converter para UTF-16 ou algo assim, o ponto está recebendo uma instância ofstream de um nome de arquivo Unicode. Antes de eu cortar a minha própria solução, há uma rota preferida aqui? Especialmente um cross-platform?
Solução
biblioteca padrão A C ++ não é Unicode-aware. char
e wchar_t
não são obrigados a ser codificações Unicode.
No Windows, wchar_t
é UTF-16, mas não há suporte direto para UTF-8 nomes de arquivos na biblioteca padrão (o tipo de dados char
não é Unicode no Windows)
Com MSVC (e, portanto, o STL Microsoft), um construtor para FileStreams é fornecido que leva um nome de arquivo const wchar_t*
, o que lhe permite criar o fluxo como:
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
No entanto, essa sobrecarga não é especificado pelo padrão 11 C ++ (que apenas garante a presença da versão base char
). Ele também não está presente em implementações STL alternativos como libstdc do GCC ++ para MinGW (-w64), a partir da versão g ++ 4.8.x.
Note que, assim como char
no Windows não é UTF8, por outro OS'es wchar_t
pode não ser UTF16. Portanto, em geral, isso não é provável que seja portátil. A abertura de um fluxo dado um nome de ficheiro wchar_t
não é definido de acordo com a norma, e especificando o nome do ficheiro em char
s pode ser difícil, porque a codificação usada por carvão animal varia entre OS'es.
Outras dicas
As versões atuais do Visual C ++ o std :: basic_fstream ter um método open()
que tomar um wchar_t * de acordo com http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx .
Desde C ++ 17, há uma maneira de plataforma cruzada para abrir uma std :: fstream com um Unicode filename usando o std :: filesystem :: caminho . Até C ++ 20, você pode criar um caminho a partir de uma string UTF-8 com std :: filesystem :: u8path . Exemplo:
std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
Depois de C ++ 20, você pode criar um caminho passando UTF-8 para o construtor:. std::filesystem::path(u8"こんにちは")
(u8path será reprovado)
Use std::wofstream
, std::wifstream
e std::wfstream
. Eles aceitam filename unicode. O nome do arquivo tem que ser wstring
, array de wchar_t
s, ou ele tem que ter _T()
macro, ou prefixo L
before o texto.
Tenha um olhar em 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;
}
Se você estiver usando Qt misturado com std::ifstream
:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));