在 bash 中,我可以通过执行以下操作将字符串 hello
的 hexdump 获取为 UTF-16:
$ echo -n "hello" | iconv -f ascii -t utf-16 | hexdump
0000000 feff 0068 0065 006c 006c 006f
000000c
我也可以像这样写一个简短的 C 程序:
int main(int argc, char **argv) {
char *str = argv[1];
hexDump("The string", str, 12);
return 0;
}
使用来自 how to get hexdump of a structure data 的 hexDump
例程. 12
是我使用上面的 hexdump
计算的字节数。
编译运行:
$ gcc test.c -o test
$ ./test $(echo -n hello | iconv -f ascii -t utf-16)
The string:
0000 ff fe 68 65 6c 6c 6f 00 53 53 48 5f ..hello.SSH_
为什么第一个十六进制字符串 feff 0068 0065 006c 006c 006f
和第二个十六进制字符串 ff fe 68 65 6c 6c 6f 00 53 53 48 5f
有区别?
我问这个是因为我正在尝试调试一个应用程序,该应用程序使用 libiconv
将 UTF-16 字符串转换为 UTF-8 并不断获取 errno
EILSEQ
这意味着 libiconv
遇到了“无效的多字节序列”。
更新:
如果我使用 -C
运行 hexdump
,我会得到以下输出:
$ echo -n hello | iconv -f ascii -t utf-16 | hexdump -C
00000000 ff fe 68 00 65 00 6c 00 6c 00 6f 00 |..h.e.l.l.o.|
0000000c
这个 hexstring 仍然不同于我的 C 程序生成的那个,因为它包含散布在 ascii 字符之间的 \x00
字节。但是,当我运行 C 程序时,根本没有散布 \x00
字节。它只有 ff fe
header ,然后是常规的 ascii 字符。
最佳答案
命令 echo -n hello | iconv -f ascii -t utf-16 | hexdump -C
只是直接在程序之间传输数据。 iconv 输出的任何字节都直接作为 hexdump 的输入。
使用命令 ./test $(echo -n hello | iconv -f ascii -t utf-16)
,shell 获取 iconv 的输出,并将其有效地粘贴到新命令中, 解析新命令,然后执行它。
因此来自 iconv 的字节是:“ff fe 68 00 65 00 6c 00 6c 00 6f 00”,shell 对此进行解析。看起来好像 shell 在解析时只是简单地跳过空字节,所以输入到程序的参数只是非空字节。由于您的字符串是 ascii,这意味着结果只是一个 ascii 字符串(前面是 UTF-16 BOM)。
我们可以使用 U+3300 (㌀) 这样的字符来演示这一点。如果我们传递这个而不是 ascii 字符并且上面是正确的,那么输出将包括 0x33(数字“3”)。
./test $(echo -n ㌀ | iconv -f utf-8 -t utf-16)
我的终端碰巧使用 UTF-8,它支持字符 U+3300,所以我让 iconv 将其转换为 UTF-16。我得到输出:
The string:
0000 ff fe 33 ..3
顺便说一下,您的程序包含数组的硬编码大小:
hexDump("The string", str, 12);
你真的不应该那样做。如果数组不是那么大,那么你会得到未定义的行为,并且你的帖子显示在真正的参数之后打印出一些垃圾(垃圾似乎是环境变量数组的开头)。这真的没有理由。只需使用正确的值:
hexDump("The string", str, strlen(str));
关于c - 为什么作为命令行参数传入的 UTF-16 字符串的 hexdump 与直接在终端上的不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21058436/