读取/写入具有纯C ++/Boost的Unicode文件名的文件 [英] Read/Write file with unicode file name with plain C++/Boost

查看:93
本文介绍了读取/写入具有纯C ++/Boost的Unicode文件名的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用boost文件系统读写具有unicode文件名的文件,在Windows(mingw)上使用boost locale(最后应与平台无关).

I want to read / write a file with a unicode file name using boost filesystem, boost locale on Windows (mingw) (should be platform independent at the end).

这是我的代码:

#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 :: exists 确实检查名称为äöü.txt的文件.但是书面文件的名称为äö¼.txt.

The fs::exists really checks for a file with the name äöü.txt. But the written file has the name äöü.txt.

阅读也有同样的问题.使用 fs :: wofstream 也不起作用,因为这只能处理广泛的输入.

Reading gives the same problem. Using fs::wofstream doesn't help either, since this just handles wide input.

如何使用C ++ 11和Boost修复此问题?

How can I fix this using C++11 and boost?

已发布错误报告: https://svn.boost.org/trac/boost/ticket/9968

要澄清赏金,使用Qt相当简单,但是我希望使用仅C ++ 11和Boost,不使用Qt且不使用ICU的跨平台解决方案.

To clarify for the bounty: It is quite simple with Qt, but I would like a cross platform solution using just C++11 and Boost, no Qt and no ICU.

推荐答案

这可能很复杂,原因有两个:

This can be complicated, for two reasons:

  1. 您的C ++源文件中有一个非ASCII字符串.如何将该文字转换为 const char * 的二进制表示形式,将取决于编译器设置和/或OS代码页设置.

  1. There's a non-ASCII string in your C++ source file. How this literal gets converted to the binary representation of a const char * would depend on compiler settings and/or OS codepage settings.

Windows仅通过UTF-16编码使用Unicode文件名,而Unix使用Unicode文件名使用UTF-8.

Windows only works with Unicode filenames through the UTF-16 encoding, while Unix uses UTF-8 for Unicode filenames.

构造路径对象

要在Windows上运行此功能,您可以尝试将文字更改为宽字符(UTF-16):

Constructing the path object

To get this working on Windows, you can try to change your literal to wide characters (UTF-16):

const wchar_t *name = L"\u00E4\u00F6\u00FC.txt";
fs::path file(name);

要获得完整的跨平台解决方案,您必须以UTF-8或UTF-16字符串开头,然后确保将其正确转换为 path :: string_type 课堂.

To get a full cross-platform solution, you'll have to start with either a UTF-8 or a UTF-16 string, then make sure it gets properly converted to the path::string_type class.

不幸的是,C ++(因而是Boost)的 ofstream API不允许将 wchar_t 字符串指定为文件名.构造函数

Unfortunately, the C++ (and thus Boost) ofstream API does not allow specifying wchar_t strings as the filename. This is the case for both the constructor and the open method.

您可以尝试确保路径对象不会立即转换为 const char * (通过使用C ++ 11字符串API),但这可能无济于事:

You could try to make sure that the path object does not get immediately converted to const char * (by using the C++11 string API) but this probably won't help:

std::ofstream(file.native()) << "Test" << std::endl;

要使Windows正常运行,您可能必须调用支持Unicode的Windows API, ,但是我不确定该 ofstream 构造函数将存在于MinGW上.

For Windows to work, you might be able have to call the Unicode-aware Windows API, CreateFileW, convert the HANDLE to a FILE *, then use the FILE * for the ofstream constructor. This is all described in another StackOverflow answer, but I'm not sure if that ofstream constructor will exist on MinGW.

不幸的是, basic_ofstream 似乎不允许自定义 basic_filebuf 类型的子类化,因此 FILE * 转换可能是唯一的(完全非-便携式)选项.

Unfortunately basic_ofstream doesn't seem to allow subclassing for custom basic_filebuf types, so the FILE * conversion might be the only (completely non-portable) option.

除了使用文件流之外,您还可以使用内存映射的I来写文件/O .根据Boost实现的方式(它不属于C ++标准库),此方法可以与Windows Unicode文件名一起使用.

Instead of using file streams, you can also write to files using memory-mapped I/O. Depending on how Boost implements this (it's not part of the C++ standard library), this method could work with Windows Unicode file names.

这是一个增强示例(取自另一个答案),该示例使用 path 对象来打开文件:

Here's a boost example (taken from another answer) that uses a path object to open the file:

#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 ++/Boost的Unicode文件名的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆