如何使用C++读取具有Unicode文件名的二进制文件?

10
在我正在处理的项目中,我需要进行相当多的字符串操作;字符串与其编码(可以是单字节或双字节)一起从二进制文件中读取。基本上,我将字符串值读取为vector<char>,读取编码,然后将所有字符串转换为wstring,以保持一致性。
这个方法工作得相当好,但是文件名本身可以是双字节字符。我完全不知道如何打开输入流。在C语言中,我会使用_wfopen函数传递wchar_t* path,但是wifstream似乎行为不同,因为它专门设计用于从文件中读取双字节字符,而不是从具有双字节文件名的文件中读取单字节。
这个问题的解决方案是什么?
编辑:在网上搜索,标准C++中似乎根本没有支持此功能(例如,请参见this discussion)。但是我想知道C++11在这个领域是否实际添加了一些有用的东西。

我会避免使用 wchar_twstring,因为 wchar_t 在不同编译器中不具备可移植性(在 VC++ 中是 16 位,在 gcc 中是 32 位)。不过 C++11 引入了 char16_tchar32_t,当然你也可以自己使用 typedef - Matthieu M.
2
在Unix系统中,内部使用除UTF-8以外的任何编码都没有意义。特别是在Linux上,您可以直接将UTF-8字符串传递给“open”函数。 - filmor
@filmor 好的,我明白了。到目前为止,我还没有在C++中处理过utf-8字符串,只是使用wstring工作。我应该实现一个string子类,比如utf8string来包装所有的转换吗?还是有更简单的方法? - Aleks G
不需要。只需使用带有UTF-8数据的std::string,因为有很多函数可以在其中进行转换(也可以在stackoverflow上找到)。但是你应该将数据设置为const。在我看来,一个接口良好的实现是http://utfcpp.sourceforge.net/。虽然我迄今为止还没有使用过它。 - filmor
1
C++11 就是标准的C++。C++03已经被取代、取消、撤回并不再是标准。 - MSalters
显示剩余4条评论
1个回答

1

传递给open函数的字符串如何映射到文件名是实现相关的。在Unix环境中,它几乎是按字面意思传递的,只有'/''\0'被特殊处理。在其他环境中,有其他规则,我曾经因为在Unix中编写了一个文件,在Windows下无法对其进行任何操作(Windows会特殊处理文件名中的':')。

另一个问题是这些文件来自哪里。如上所述,在您的系统上可能根本没有打开它们的方法:在Windows中,带有':'的文件名根本无法打开。在Unix中,如果文件名本身包含'\0'字符,则可能也无法读取它们,并且UTF16文件名在Unix下将显示为其中包含'\0'字符。您唯一的解决方案可能是使用生成文件的系统上的本机工具来重命名它们。

我不太清楚在Unix磁盘上如何获得这样的文件名。当SMB服务器(例如Samba)在Windows系统上提供服务时,它如何映射UTF16文件名?或者NFS服务器呢?我认为这些东西在Windows下也存在。


在Linux中,文件名到UTF-8(标准代码页)的映射是由驱动程序完成的,这通常可以进行配置(例如,对于cifs(smb)可以使用挂载选项iocharset)。 - filmor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接