使用普通C / Boost读取/写入具有unicode文件名的文件

前端之家收集整理的这篇文章主要介绍了使用普通C / Boost读取/写入具有unicode文件名的文件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想使用boost文件系统读取/写入具有unicode文件名的文件,在 Windows(mingw)上升级区域设置(最终应该是平台无关的).

这是我的代码

#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字符串作为文件名. constructoropen 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;
}

猜你在找的C&C++相关文章