加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 03:16:06 所属栏目:百科 来源:网络整理
导读:我想使用boost文件系统读取/写入具有unicode文件名的文件,在 Windows(mingw)上升级区域设置(最终应该是平台无关的). 这是我的代码: #include boost/locale.hpp#define BOOST_NO_CXX11_SCOPED_ENUMS#include boost/filesystem.hpp#include boost/filesystem/
我想使用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"u00E4u00F6u00FC.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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读