C++库中的文件打开界面是否应该在Windows上使用UTF-8?

zeu*_*xcg 9 c++ windows unicode encoding utf-8

我正在开发一个库(pugixml),除其他外,它使用窄字符C字符串为XML文档提供文件加载/保存API:

bool load_file(const char* path);
bool save_file(const char* path);
Run Code Online (Sandbox Code Playgroud)

目前路径是逐字传递给的fopen,这意味着在Linux/OSX上你可以传递一个UTF-8字符串来打开文件(或任何其他有效路径的字节序列),但在Windows上你必须使用Windows ANSI编码 - UTF-8不起作用.

文档数据(默认情况下)使用UTF-8表示,因此如果您有一个带有文件路径的XML文档,您将无法将从文档中检索到的路径传递给load_file按原样运行 - 或者更确切地说,这不会在Windows上工作.该库提供了使用的替代函数wchar_t:

bool load_file(const wchar_t* path);
Run Code Online (Sandbox Code Playgroud)

但是使用它们需要额外的努力来将UTF8编码为wchar_t.

一种不同的方法(由SQlite和GDAL使用 - 不确定是否有其他C/C++库这样做)涉及在Windows上将路径视为UTF-8(可通过将其转换为UTF-16并使用a wchar_t-aware函数喜欢_wfopen打开文件).

我可以看到不同的利弊,我不确定哪种权衡是最好的.

一方面,在所有平台上使用一致的编码肯定是好的.这意味着您可以使用从XML文档中提取的文件路径来打开其他XML文档.此外,如果使用该库的应用程序采用UTF-8,则在通过库打开XML文件时不必进行额外的转换.

另一方面,这意味着文件加载的行为不再与标准函数的行为相同 - 因此通过库的文件访问不等同于通过标准fopen/的文件访问std::fstream.似乎虽然有些库采用UTF-8路径,但这在很大程度上是一个不受欢迎的选择(这是真的吗?),因此如果应用程序使用许多第三方库,它可能会增加混乱而不是帮助开发人员.

例如,传递argv[1]load_file目前适用于使用Windows的系统的locale编码的编码路径(例如,如果你有一个俄罗斯的区域,那么你可以加载与俄罗斯的名字,如任何文件,但你不能用日文字符加载文件).切换到UTF-8意味着只有ASCII路径才能工作,除非您以某种其他Windows特定方式检索命令行参数.

当然,对于图书馆的一些用户来说,这将是一个重大改变.

我在这里错过了什么重点吗?是否有其他图书馆采用相同的方法?什么是更好的C++ - 在文件访问中始终不一致,或争取统一的跨平台行为?

请注意,问题是关于打开文件的默认方式 - 当然没有什么能阻止我用_utf8后缀添加另一对函数或以其他方式指示路径编码.

nne*_*neo 8

越来越多的人认为,您应该只在跨平台代码中使用UTF-8,并在适当的情况下在Windows中自动执行转换.utf8everywhere给出了更喜欢UTF-8编码的理由.

作为最近的一个例子,libtorrent弃用了处理wchar_t文件名的所有例程,而是要求库用户在传入文件名之前使用他们的wchar_t-to-utf8转换函数.

就个人而言,我必须避免wchar_t/使用的最强大的原因wstring就是避免重复我的API.保持API中的功能数量减少,以减少外部维护,文档和代码路径重复成本是很有价值的.细节可以在内部解决.由Windows ANSI/Unicode拆分引起的重复API的混乱可能足以避免在您自己的API中出现这种情况.

  • 是的,更具体地说是在Windows上,**将文件名转换为宽字符并使用广泛的API**.那里有很多库,它只是将`const char*`传递给`fopen(...)`,这将有效地使得无法打开具有任意文件名的文件(即当前代码页之外的字符). (2认同)