Como abrir uma std :: fstream (ofstream ou ifstream) com um nome de arquivo unicode?

StackOverflow https://stackoverflow.com/questions/821873

  •  03-07-2019
  •  | 
  •  

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?

Foi útil?

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 chars 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_ts, ou ele tem que ter _T() macro, ou prefixo Lbefore 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()));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top