Andrew Beatty
Andrew Beatty

Reputation: 938

How to open an std::fstream (ofstream or ifstream) with a unicode filename?

You wouldn't imagine something as basic as opening a file using the C++ standard library for a Windows application was tricky ... but it appears to be. By Unicode here I mean UTF-8, but I can convert to UTF-16 or whatever, the point is getting an ofstream instance from a Unicode filename. Before I hack up my own solution, is there a preferred route here ? Especially a cross-platform one ?

Upvotes: 78

Views: 78508

Answers (7)

Nikolai
Nikolai

Reputation: 3134

Since C++17, there is a cross-platform way to open an std::fstream with a Unicode filename using the std::filesystem::path overload. Example:

std::ofstream out(std::filesystem::path(u8"こんにちは"));
out << "hello";

Upvotes: 36

Andreas Haferburg
Andreas Haferburg

Reputation: 5510

If you're using Qt mixed with std::ifstream:

return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));

Note that the std::basic_ifstream constructor normally doesn't accept a const w_char*, but on in the MS implementation of STL it does. With other implementations you would probably call qString.utf8(), and use the const char* ctor.

Upvotes: 0

Michael Haephrati
Michael Haephrati

Reputation: 4215

Use

wfstream

instead of

fstream

and

wofstream

instead of

ofstream

and so on... You can find this information in the iosfwd header file.

Upvotes: 1

jhasse
jhasse

Reputation: 2593

Have a look at 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;
}

Upvotes: 0

Brackets
Brackets

Reputation: 572

Use std::wofstream, std::wifstream and std::wfstream. They accept unicode filename. File name has to be wstring, array of wchar_ts, or it has to have _T() macro, or prefix Lbefore the text.

Upvotes: 0

Stack Overflow is garbage
Stack Overflow is garbage

Reputation: 247899

The C++ standard library is not Unicode-aware. char and wchar_t are not required to be Unicode encodings.

On Windows, wchar_t is UTF-16, but there's no direct support for UTF-8 filenames in the standard library (the char datatype is not Unicode on Windows)

With MSVC (and thus the Microsoft STL), a constructor for filestreams is provided which takes a const wchar_t* filename, allowing you to create the stream as:

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

However, this overload is not specified by the C++11 standard (it only guarantees the presence of the char based version). It is also not present on alternative STL implementations like GCC's libstdc++ for MinGW(-w64), as of version g++ 4.8.x.

Note that just like char on Windows is not UTF8, on other OS'es wchar_t may not be UTF16. So overall, this isn't likely to be portable. Opening a stream given a wchar_t filename isn't defined according to the standard, and specifying the filename in chars may be difficult because the encoding used by char varies between OS'es.

Upvotes: 64

John Downey
John Downey

Reputation: 14114

The current versions of Visual C++ the std::basic_fstream have an open() method that take a wchar_t* according to http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx.

Upvotes: 4

Related Questions