使用std::filesystem::path将UTF8转换为UTF16

3

从C++11开始,可以使用std::codecvt_utf8_utf16将UTF8转换为UTF16 wchar_t(至少在Windows上,其中wchar_t宽度为16位):

std::wstring utf8ToWide( const char* utf8 )
{
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    return converter.from_bytes( utf8 );
}

很遗憾在 C++17 中,std::codecvt_utf8_utf16被废弃了。但是有一个std::filesystem::path具有所有可能的转换功能,例如,它具有成员函数。
std::string string() const;
std::wstring wstring() const;
std::u8string u8string() const;
std::u16string u16string() const;
std::u32string u32string() const;

因此,上述函数可以重写如下:
std::wstring utf8ToWide( const char* utf8 )
{
    return std::filesystem::path( (const char8_t*) utf8 ).wstring();
}

std::codecvt_utf8_utf16 不同,此编码转换器不会使用任何已弃用的 C++ 代码。

这样的转换器可能会有什么缺点?例如,路径长度不能超过某个长度或某些 Unicode 符号在其中被禁止使用吗?


2
@PanagiotisKanavos “这个问题没有好的解决方案” 虽然没有一个好的标准解决方案,但我认为有一个好的解决方案:使用库。 - eerorika
1
@eerorika 或者操作系统函数。我想知道 path 实现是做什么的。或者继续使用 codecvt_utf8_utf16 - Panagiotis Kanavos
1
@PanagiotisKanavos 我们的选择是:使用库的已弃用部分,使用std::filesystem::path进行额外复制,或者使用MultiByteToWideChar。不管怎样,OP似乎在使用Windows。 - Ayxan Haqverdili
3
使用std::filesystem::path进行UTF8到UTF16的转换,对我来说有些像滥用一个函数来做其他事情。实际上,我仍然相信UTF-16<->UTF-8转换可以通过相当简单的位运算实现(这是概念的一部分)。我更喜欢手动编写的(并经过仔细测试)函数,而不是已经弃用的codecvt_utf8_utf16(),即使在后者变得可用之前我也使用过它。(除非有人告诉我有很好的理由不这么做。) - Scheff's Cat
2
@PanagiotisKanavos:“手工制作的方法与操作系统方法在边缘情况下会有所不同,这会给开发人员和最终用户带来不愉快的惊喜。”... 不,不会。UTF-8和UTF-16都是相当简单的数字转换,并且它们对Unicode的整个21位范围都有明确定义。这不是难写的复杂代码。一个合格的程序员实现这些东西不需要超过4个小时,你可能需要额外的时间来测试特定的情况。 - Nicol Bolas
显示剩余9条评论
1个回答

2
这种转换器可能会带来哪些缺点呢?
首先,对于不了解你在做什么的用户来说,这是没有意义的。使用路径类型进行UTF-8到16的转换是荒谬的,并且应该立即被视为代码异味。这是一种可怕的hack,当你不必要地不愿意下载一个可以正确完成工作的简单库时才会这样做。
其次,它不一定能正常工作。路径(path)用于存储路径。因此,名称也是这样。具体而言,它们用于以文件系统易于消费的方式存储路径。因此,在path 中存储的字符串可以有任何文件系统想要放在它上面的限制,除了C++标准要求它执行的少量操作之外。
例如,如果文件系统不区分大小写(甚至只是ASCII不区分大小写),则将所有字符串转换为小写字母并将其存储在path中就是一种合法的实现方式。或者在从path中提取它们时将它们转换成小写字母。或者类似的操作。 path 可以将所有的\转换为/。或者将你的:转换为/。或者执行任何其他依赖于实现的技巧。
如果你害怕使用已弃用的设施,只需下载一个简单的UTF-8/16转换库。或者自己编写一个;这并不难。

路径可以将所有的\s转换为/。或者将你的:转换为/'s。实际上,我认为只有显式调用std::filesystem::path::make_preferred才能这样做。 - Fedor

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