这是我的代码:
#include <boost/locale.hpp> #define BOOST_NO_CXX11_SCOPED_ENUMS #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> namespace fs = boost::filesystem; #include <string> #include <iostream> int main() { std::locale::global(boost::locale::generator().generate("")); fs::path::imbue(std::locale()); fs::path file("äöü.txt"); if (!fs::exists(file)) { std::cout << "File does not exist" << std::endl; } fs::ofstream(file,std::ios_base::app) << "Test" << std::endl; }
fs ::存在真正检查名称为äöü.txt的文件.
但书面文件的名称是äöü.txt.
阅读也有同样的问题.使用fs :: wofstream也没有帮助,因为这只是处理宽输入.
如何解决这个使用C 11和提升?
编辑:错误报告发布:https://svn.boost.org/trac/boost/ticket/9968
为了澄清赏金:这是很简单的Qt,但我想要一个跨平台解决方案只使用C 11和Boost,没有Qt和没有ICU.
解决方法
> C源文件中有一个非ASCII字符串.如何将此文字转换为const char *的二进制表示形式将取决于编译器设置和/或操作系统代码页设置.
> Windows仅通过UTF-16编码与Unicode文件名一起使用,而Unix则使用UTF-8作为Unicode文件名.
构建路径对象
要在Windows上工作,您可以尝试将文字更改为宽字符(UTF-16):
const wchar_t *name = L"\u00E4\u00F6\u00FC.txt"; fs::path file(name);
要获得一个完整的跨平台解决方案,您必须从UTF-8或UTF-16字符串开始,然后确保它正确转换为path :: string_type类.
打开文件流
不幸的是,Stream API的C(和Boost)不允许指定wchar_t字符串作为文件名. constructor和open
method都是这样.
您可以尝试确保路径对象不会立即转换为const char *(通过使用C 11字符串API),但这可能不会有帮助:
std::ofstream(file.native()) << "Test" << std::endl;
要使Windows工作,您可能必须调用支持Unicode的Windows API,CreateFileW
,将HANDLE转换为FILE *,然后使用FILE *作为stream构造函数.这是所有described in another StackOverflow answer,但我不知道如果该构造函数将在MinGW上存在.
不幸的是,basic_ofstream似乎不允许自定义basic_filebuf类型的子类化,因此FILE *转换可能是唯一的(完全不可移植的)选项.
而不是使用文件流,您也可以使用memory-mapped I/O写入文件.根据Boost实现的方式(它不是C标准库的一部分),此方法可以与Windows Unicode文件名一起使用.
这是一个使用路径对象打开文件的升级示例(从another answer开始):
#include <boost/filesystem.hpp> #include <boost/iostreams/device/mapped_file.hpp> #include <iostream> int main() { boost::filesystem::path p(L"b.cpp"); boost::iostreams::mapped_file file(p); // or mapped_file_source std::cout << file.data() << std::endl; }