如何将百分比编码的字符串转换为UTF-8编码并使用UTF-8字符串创建目录

时间:2013-01-18 06:52:23

标签: linux utf-8

我有一个百分比编码的字符串:%DB%81%DB%8C%D9%84%D9%88/ 我通过复制十六进制字节(UTF-8 encoded string - > %hh)将其转换为0xhh

UTF-8编码字符串:str = U+00DB U+0081 U+00DB U+008C U+00D9 U+0084 U+00D9 U+0088

在八月:\333\201\333\214\331\204\331\201

但是创建目录的名称是Û ÛŒÙ„Ùˆ(有些乱码),而不是یلو/。我知道在Linux中我们可以创建任何语言名称的目录(乌尔都语,中文等,如果名称以UTF-8编码)

此外,机器的区域设置设置为en_US.UTF-8

有什么想法吗?

感谢@kmkamplan,我也使用几乎相同的逻辑来逐字节复制,但目录名仍然是乱码。如果您的系统目录名称为یلو/,那么我认为charset设置存在一些问题。我的charset / encoding设置为en_US.UTF-8。请帮我解决这个奇怪的行为。感谢。

我得到了:

<00> 0000cd0 3034 3639 4a20 6e61 3120 2038 3631 333a

0000ce0 2034 81db 8cdb 84d9 88d9 000a

0000ceb

请参阅下面的评论。感谢

1 个答案:

答案 0 :(得分:4)

UTF-8和Unicode之间存在混淆。解码%DB%81%DB%8C%D9%84%D9%88将为您提供字节 0xDB 0x81 0xDB 0x8C 0xD9 0x84 0xD9 0x88。显然,这是一个由阿拉伯字符组成的 UTF-8 编码字符串。如果您将其读作UTF-8并将其解码为Unicode代码点,则会得到:

  • 0xDB 0x81→U + 06C1阿拉伯字母heh目标(ہ),
  • 0xDB 0x8C→U + 06CC阿拉伯语字母波斯语yeh(ہی),
  • 0xD9 0x84→U + 0644阿拉伯文字母lam(ل),
  • 0xD9 0x88→U + 0648阿拉伯语字母waw(و)。

这不应与您实际解码的内容相混淆:

  • U + 00DB拉丁大写字母U与抑扬(Û),
  • U + 0081
  • U + 0084
  • U + 0088
  • U + 008C
  • U + 00D9拉丁大写字母U,带有坟墓(Ù),

此外,Unix文件名实际上由 bytes 组成,而不是字符。因此,您可以选择如何显示它们。

因此,对于这种情况最简单的方法可能是将百分比解码为字节,并使用这些字节作为文件名创建目录,不用将它们转换为实际的Unicode字符。

这是一个有效的例子:

#include <sys/stat.h>
#include <string>

const int hex_value[256] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
  0,10,11,12,13,14,15
};

int main(int argc, char **argv)
{
  std::string str("%DB%81%DB%8C%D9%84%D9%88");

  size_t t = 0;
  for (size_t s = 0; s < str.size(); s++) {
    if (str[s] == '%' && s + 2 < str.size()) {
      str[t] = hex_value[str[s+1]] * 16 + hex_value[str[s+2]];
      s += 2;
    }
    else
      str[t] = str[s];
    t++;
  }
  str.resize(t);

  mkdir(str.c_str(), 0755);
}

如果您仍然在终端上看到除ہیلو以外的其他内容,则可能是您的终端对其应使用的字符集感到困惑。要清除这种可能的混淆,请将ls的输出通过hexdump,并确保您看到了您期望的字节:

$ ls | hexdump
0000000 61 2e 6f 75 74 0a 63 6c 65 61 6e 2e 70 68 70 0a
…
00000c0 32 32 2e 63 6f 6d 3a 32 32 0a db 81 db 8c d9 84
00000d0 d9 88 0a                                       
00000d3

您可以在此处清楚地看到正确的文件名db 81 db 8c d9 84 d9 88 0a