跨平台 unicode 路径处理

Posted

技术标签:

【中文标题】跨平台 unicode 路径处理【英文标题】:Cross platform unicode path handling 【发布时间】:2009-11-20 08:06:05 【问题描述】:

我正在使用 boost::filesystem 进行跨平台路径操作,但是当需要将调用分解为我无法控制的不接受 UTF-8 的接口时,它就会崩溃。例如,在使用 Windows API 时,我需要转换为 UTF-16,然后调用我将要调用的任何函数的宽字符串版本,然后将任何输出转换回 UTF-8。

虽然许多 boost::filesystem 函数的 wpath 和其他 w* 形式有助于保持理智,但对于如何在需要时最好地处理向宽字符串形式的转换,同时保持一致性,有什么建议吗?在我自己的代码中?

【问题讨论】:

【参考方案1】:

嗯,最简单的方法是创建某种通用例程,该例程将返回以您希望的方式为提供的路径或路径周围的包装类编码的字符串。

boost::filesystem::wpath boostPath( L"c:\\some_path" );
MyPathWrapper p( boostPath );
std::wstring sUtf8 = p.file_string_utf8();
std::wstring sUtf16 = p.file_string_utf16();
// or
std::wstring sUtf8 = p.file_string( CP_UTF8 );
// ...

类似的东西。

【讨论】:

请注意,utf8 由stringchar * 表示。但有趣的想法,我得考虑一下 这是迄今为止我见过的最好的解决方案。【参考方案2】:

我做了什么:

struct vpath_traits;

typedef boost::filesystem::basic_path<std::string, vpath_traits> vpath;

// utf8 
struct vpath_traits

  typedef std::string internal_string_type;
  typedef std::wstring external_string_type;
  static external_string_type to_external(
      const vpath &, const internal_string_type &src);
  static internal_string_type to_internal(const external_string_type &src);
;


namespace boost 
  namespace filesystem 
    template<> struct is_basic_path<vpath>
     BOOST_STATIC_CONSTANT( bool, value = true ); ;
  


// convenient functions for converting vpath to and from
// whatever API you may be using.

std::string    vpathToWin32Byte(const vpath &src);
vpath          vpathFromWin32Byte(const std::string &str);
vpath          vpathFromWin32Byte(const char *str);

std::wstring   vpathToWin32Wide(const vpath &src);
vpath          vpathFromWin32Wide(const std::wstring &str);
vpath          vpathFromWin32Wide(const wchar_t *str);

QDir           vpathToQDir(const vpath &src);
vpath          vpathFromQDir(const QDir &qdir);

注意:

您必须以某种方式实现方法vpath_traits::to_externalvpath_traits::to_internal。中可能有一些 utf8-converter 促进。但是我将utf8实现到ucs-16并支持自己,但它是 既不漂亮也不完整,所以你最好使用一些标准 实施。

它适用于我们的代码。例如:

namespace fs = boost::filesystem;
...

vpath dstFile = dstDir / filePath;
bool success = true;

try  fs::remove(dstFile); 
catch (fs::basic_filesystem_error<vpath> & /* e */)  success = false;

if (success) 
  try  fs::copy_file(srcFile, dstFile); 
  catch (fs::basic_filesystem_error<vpath> & /* e */)  success = false;


...

【讨论】:

hm,并没有真正提供任何优势,并且破坏了使用 pathwpath 便利功能的能力【参考方案3】:

什么对我有用:

Windows:std::wstring 是 utf16,所以 "::CreateFileW(Path.file_string().c_str()," ... 有效 posix:需要转为utf8,解决方法:UTF8 to/from wide char conversion in STL

【讨论】:

以上是关于跨平台 unicode 路径处理的主要内容,如果未能解决你的问题,请参考以下文章

Unicode(统一码万国码单一码)

Question20180127 Java程序员详述编码Unicode

Unicode字符串和非Unicode字符串

unicode汉语翻译是啥意思

Unicode与编码方式

纯 C++ 中的 Unicode 字符串