C++ 如何使用 unicode 文件名打开 std::fstream(ofstream 或 ifstream)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/821873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:26:27  来源:igfitidea点击:

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

c++windowsunicode

提问by Extreme Rationalist

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 ?

您不会想象像使用 Windows 应用程序的 C++ 标准库打开文件这样基本的事情是棘手的......但它似乎是。这里的 Unicode 是指 UTF-8,但我可以转换为 UTF-16 或其他格式,重点是从 Unicode 文件名获取 ofstream 实例。在我修改自己的解决方案之前,这里有首选路线吗?尤其是跨平台的?

回答by jalf

The C++ standard library is not Unicode-aware. charand wchar_tare not required to be Unicode encodings.

C++ 标准库不支持 Unicode。char并且wchar_t不需要是 Unicode 编码。

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

在 Windows 上,wchar_t是 UTF-16,但标准库中不直接支持 UTF-8 文件名(charWindows 上的数据类型不是 Unicode)

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:

使用 MSVC(以及 Microsoft STL),提供了一个const wchar_t*文件流构造函数,它采用文件名,允许您将流创建为:

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 charbased version). It is also not present on alternative STL implementations like GCC's libstdc++ for MinGW(-w64), as of version g++ 4.8.x.

但是,C++11 标准并未指定此重载(它仅保证char基于版本的存在)。从版本 g++ 4.8.x 开始,它也不存在于替代 STL 实现中,例如 GCC 的 libstdc++ for MinGW(-w64)。

Note that just like charon Windows is not UTF8, on other OS'es wchar_tmay not be UTF16. So overall, this isn't likely to be portable. Opening a stream given a wchar_tfilename 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.

请注意,就像char在 Windows 上不是 UTF8 一样,在其他操作系统上wchar_t可能不是 UTF16。所以总的来说,这不太可能是便携的。打开给定wchar_t文件名的流不是根据标准定义的,并且在chars 中指定文件名可能很困难,因为 char 使用的编码因操作系统而异。

回答by Nikolai

Since C++17, there is a cross-platform way to open an std::fstream with a Unicode filename using the std::filesystem::pathoverload. Until C++20, you can create a path from a UTF-8 string with std::filesystem::u8path. Example:

从 C++17 开始,有一种跨平台的方法可以使用std::filesystem::path重载打开带有 Unicode 文件名的 std::fstream 。在 C++20 之前,您可以使用std::filesystem::u8path从 UTF-8 字符串创建路径。例子:

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

After C++20, you can create a path by passing UTF-8 to the constructor: std::filesystem::path(u8"こんにちは")(u8path will be deprecated).

在 C++20 之后,您可以通过将 UTF-8 传递给构造函数来创建路径std::filesystem::path(u8"こんにちは"):(不推荐使用 u8path)。

回答by John Downey

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.

open()根据http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx,当前版本的 Visual C++ std::basic_fstream 有一个采用 wchar_t*的方法。

回答by Brackets

Use std::wofstream, std::wifstreamand 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.

使用std::wofstream,std::wifstreamstd::wfstream。他们接受 unicode 文件名。文件名必须是swstring数组wchar_t,或者它必须在文本前有_T()宏或前缀L

回答by jhasse

Have a look at Boost.Nowide:

看看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;
}

回答by Andreas Haferburg

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

如果您使用 Qt 与std::ifstream

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