如何读取 UTF-16 文件并将其内容与使用十六进制值定义的 wchar_t* 字符串文字进行比较

Posted

技术标签:

【中文标题】如何读取 UTF-16 文件并将其内容与使用十六进制值定义的 wchar_t* 字符串文字进行比较【英文标题】:How to read a UTF-16 file and compare it's contents to a wchar_t* string literal defined with hex values 【发布时间】:2015-07-21 23:09:14 【问题描述】:

我有一个 UTF-16(或 UCS-2,因为据我所知它是 UTF-16 LE)编码的文件,我从这里下载:http://www.humancomp.org

我想将该文件的内容读入std::wstring,这是我的第一个问题:我还不能正确读取该文件。读取的数据似乎总是乱七八糟。

其次,我想将读取的std::wstringconst wchar_t* 字符串文字进行比较。在这里,我遇到了第二个问题:如何通过十六进制值指定 wchar_t 内容?

我要转换为const wchar_t* 字符串文字的文件具有以下字节(从十六进制编辑器中复制)

FE FF 05 31 05 65 05 81 05 65 05 70 05 6B 00 20 05 6B 05 74 00 20 05 6C 05 61 05 7E 00 20 00 3F 05 82 05 72 05 6B 056 65 05 6B 056 65 05 6 20 0C 7E 05 61 05 80 05 61 05 80 00 2C 00 0D 00 0A 05 3F 05 75 05 61 05 65 05 62 05 7D 00 20 05 79 05 7F 05 61 05 75 05 6B 00 20 05 6F 05 61 05 7D 05 6F 05 61 05 6E 05 6B 00 20 05 74 05 70 05 63 05 6B 05 65 00 2E 00 2E 00 2E 00 0D 00 0A 05 31 05 75 05 65 05 7A 05 70 05 7D 00 20 05 6F 00 3F 05 82 05 66 05 70 05 6B 00 20 05 74 05 70 05 6F 05 65 00 20 05 6B 05 65 05 6E 00 20 00 3F 05 61 05 7E 05 61 05 7F 05 80 00 2C 00 0D 00 0A 05 31 05 75 05 65 05 7A 05 70 05 7D 00 20 05 6F 00 3F 05 82 05 66 05 70 05 6B 00 20 00 3F 05 61 05 7E 05 61 05 7F 05 61 05 6C 00 20 05 74 05 70 05 6F 05 05 8 905 05 6F 05 8 >

当然,我不能用它来初始化字符串文字。我尝试将其转换为十六进制值并应用reinterpret_cast 来获得const wchar_t*

reinterpret_cast("\xFE\xFF\x05\x31\x05\x65\x05\x81\x05\x65\x05\x70\x05\x6B\x00\x20\x05\x6B\x05\ x74\x00\x20\x05\x6C\x05\x61\x05\x7E\x00\x20\x00\x3F\x05\x82\x05\x72\x05\x6B\x05\x65\x00\x20\x05\x6C\ x05\x61\x05\x7E\x05\x61\x05\x80\x05\x61\x05\x80\x00\x2C\x00\x0D\x00\x0A\x05\x3F\x05\x75\x05\x61\x05\ x65\x05\x62\x05\x7D\x00\x20\x05\x79\x05\x7F\x05\x61\x05\x75\x05\x6B\x00\x20\x05\x6F\x05\x61\x05\x7D\ x05\x6F\x05\x61\x05\x6E\x05\x6B\x00\x20\x05\x74\x05\x70\x05\x63\x05\x6B\x05\x65\x00\x2E\x00\x2E\x00\ x2E\x00\x0D\x00\x0A\x05\x31\x05\x75\x05\x65\x05\x7A\x05\x70\x05\x7D\x00\x20\x05\x6F\x00\x3F\x05\x82\ x05\x66\x05\x70\x05\x6B\x00\x20\x05\x74\x05\x70\x05\x6F\x05\x65\x00\x20\x05\x6B\x05\x65\x05\x6E\x00\ x20\x00\x3F\x05\x61\x05\x7E\x05\x61\x05\x7F\x05\x80\x00\x2C\x00\x0D\x00\x0A\x05\x31\x05\x75\x05\x65\ x05\x7A\x05\x70\x05\x7D\x00\x20\x05\x6F\x00\x3F\x05\x82\x05\x66\x05\x70\x05\x6B\x00\x20\x00\x3F\x05\ x61\x05\x7E\x05\x61\x05\x7F\x05\x61\x05\x6C\x00\x20\x05\x74\x05\x70\x05\x6F\x05\x6B\ x05\x65\x05\x89");

但这不起作用。它给了我虚假数据。

我也尝试过直接创建wchar_t 字符串文字:

L"\xFEFF\x0531\x0565\x0581\x0565\x0570\x056B\x0020\x056B\x0574\x0020\x056C\x0561\x057E\x0020\x003F\x0582\x0572\x0560\x056C5\x0 x0561 \ x057e \ x0561 \ x0580 \ x0580 \ x0580 \ x0580 \ x0075 \ x0562 \ x0575 \ x0561 \ x0565 \ x0562 \ x0565 \ x0562 \ x057d \ x0020 \ x057d \ x0020 \ x0579 \ x057f \ x0561 \ x0575 \ x0561 \ x0020 \ x056b \ x0020 \ x056b \ x0561 \ x057d \ x056f \ x0561 \ x0520 \ x0574 \ x0570 \ x0574 \ x0560 \ x0574 \ x056b \ x0565 \ x006b \ x0065 \ x002e \ x0065 \ x002e \ x0065 \ x002e \ x000d \ x000a \ x0031 \ x0575 \ x0565 \ x0575 \ x0565 \ x057a \ x0570 \ x057d \ x0020 \ x056f \ x0030 \ x056f \ x0030 \ x057d \ x0020 \ x057d \ x0020 \ x0566 \ x0570 \ x056b \ x0020 \ x0570 \ x002520 \ x0560 \ x002520 \ x056b \ x0560 \ x056b \ x0565 \ x0560 \ x0565 \ x0565 \ x0565 \ x0565 \ x002560 \ x0020 \ x003f \ x0561 \ x0561 \ x057f \ x0561 \ x057e \ x0561 \ x057e \ x0561 \ x057f \ x0561 \ x057f \ x057f \ x057f \ x0580 \ x057f \ x0580 \ x057A \ x0570 \ x057D \ x0020 \ x056F \ x003F \ x0582 \ x0566 \ x0570 \ x056B \ x0020 \ x003F \ x0561 \ x057E \ x0561 \ x057F \ x0561 \ x056C \ x0020 \ x0574 \ x0570 \ x056F \ x056B \ x0565 \ x0589" 

这再次以虚假数据告终。我什至不确定这是否是指定 wchar_t 数据的正确方法 - 组合 2 个字节?

【问题讨论】:

文件的字节是 UTF-16BE (从 UTF-16BE BOM 的存在可以看出)。如果您的字符串文字是在 UTF-16LE 中,则必须先进行转换,然后才能比较它们。原始文字字节的 reinterpret_cast 很好,除了最后会得到垃圾,因为您没有在 UTF-16 中包含空终止符:\x00\x00。您的 L"..." 文字以 null 正确终止。 要将 UTF-16BE 编码文件读入 std::wstring,请使用经过 imbue()'ed 的 std::wifstream 和代表 UTF-16BE 的 std::locale 对象。如果您使用的是 C++11,则可以创建一个 std::locale,它使用 std::codecvt_utf16 类并启用其 std::consume_header 标志,这样它将考虑 BOM。 【参考方案1】:

这是在 Remy Lebeau 的评论帮助下实现的解决方案:

// BOM: \xFEFF
auto utf16raw = L"\x0531\x0565\x0581\x0565\x0570\x056B\x0020\x056B\x0574\x0020\x056C\x0561\x057E\x0020\x003F\x0582\x0572\x056B";
std::wstring utf16strutf16raw;

BOM 必须不在字符串中。 例如,UTF-16 字符串 utf16str 可以转换为带有 UTF-8 CPP library available on Sourceforge 的 UTF-8 编码字符串(反之亦然)。

【讨论】:

如果允许使用 C++11 或更高版本,则仅需要标准库即可在 UTF-8 和 UTF-16 之间进行转换。参考***.com/a/18597384/6345。

以上是关于如何读取 UTF-16 文件并将其内容与使用十六进制值定义的 wchar_t* 字符串文字进行比较的主要内容,如果未能解决你的问题,请参考以下文章

读取二进制数据并将其转换为十六进制

我如何在linux / unix / bash脚本中搜索文件中的十六进制内容?

C ++读取二进制文件并转换为十六进制

使用scanf从用户输入十六进制指令并将其保存在char中。 (C)

如何将Mac地址转换为十六进制并将其传递给java中的字节数组

如何使用 setfill 和 setw 在字符串变量中存储十六进制值