Php 如何转换格式错误的数据库字符(ascii到utf-8)

Php 如何转换格式错误的数据库字符(ascii到utf-8),php,character-encoding,non-ascii-characters,Php,Character Encoding,Non Ascii Characters,我知道很多人会说这个问题已经得到了这样的回答,但让我解释一下为什么它不那么直截了当 我想用PHP将“看起来像ascii”的东西转换成“utf-8” 有一个网站可以做到这一点 当我输入这个字符串时,我返回Z⬦Z这是正确的输出 我尝试了iconv和一些mb函数。虽然我不知道这些函数是否能够实现我想要的功能,或者我需要哪些选项。如果无法使用这些函数,请使用一些自行编写的PHP代码。(该网站运行javascript,我不认为PHP在这方面的能力有所下降) 需要明确的是:目标是用PHP重新创建该网站正在做

我知道很多人会说这个问题已经得到了这样的回答,但让我解释一下为什么它不那么直截了当

我想用PHP将“看起来像ascii”的东西转换成“utf-8”

有一个网站可以做到这一点

当我输入这个字符串时,我返回
Z⬦Z
这是正确的输出

我尝试了
iconv
和一些
mb
函数。虽然我不知道这些函数是否能够实现我想要的功能,或者我需要哪些选项。如果无法使用这些函数,请使用一些自行编写的PHP代码。(该网站运行javascript,我不认为PHP在这方面的能力有所下降)

需要明确的是:目标是用PHP重新创建该网站正在做的事情。不要对ascii和utf-8进行语义辩论

编辑:使用

它可以根据编码标准对任何标量Unicode码点值进行编码/解码


标准链接到,所以这个库说它实现了标准,那么PHP呢?

UTF-8是ASCII的超集,所以从ASCII转换为UTF-8就像将汽车转换成汽车一样

+--- UTF-8 ---------------+
|                         |
|   +--- ASCII ---+       |
|   |             |       |
|   +-------------+       |
+-------------------------+
您链接的工具似乎使用术语“ASCII”作为同义词(它表示“汽车”,但表示“废金属”)。Mojibake通常是这样发生的:

  • 您选择了一个非英语字符:

  • 使用UTF-8对其进行编码:
    0xE2 0xAC 0xA6

  • 您可以在配置为使用您所在地区广泛使用的单字节编码的工具中打开流:

  • 在单字节编码的字符表中查找UTF-8字符的各个字节:

    • 0xE2
      ->
    • 0xAC
      ->
    • 0xA6
      ->
  • 将生成的字符编码为UTF-8:

    • 0xC3 0xA2
    • =
      0xC2 0xAC
    • ==
      0xC2 0xA6
  • 因此,您已经转换了UTF-8流
    0xE2 0xAC 0xA6
    )也输入UTF-8流
    0xC3 0xA2 0xC2 0xAC 0xC2 0xA6

    要撤消此操作,需要反向执行这些步骤。如果您知道使用了什么代理编码(在我的示例中是Windows-1252),那么这很简单:

    但如果你不这样做,那就很棘手了。我想你可以:

  • 编译一个字典,把你在不同的单字节编码中得到的不同字节序列编成字典,然后使用某种贝叶斯推理找出最可能的编码。(我真的帮不了你。)

  • 尝试最可能的编码并目视检查输出,以确定哪个是正确的:

    // Source code saved as UTF-8
    $mojibake = "Z…Z";
    foreach (mb_list_encodings() as $proxy) {
        $original = mb_convert_encoding($mojibake, $proxy, 'UTF-8');
        echo $proxy, ': ', $original, PHP_EOL;
    }
    
  • 如果(在您的案例中)您知道原始文本是什么,并且您确信没有混合编码,请按#2执行,但尝试PHP支持的所有编码:

    // Source code saved as UTF-8
    $mojibake = 'Z…Z';
    $expected = 'Z⬦Z';
    foreach (mb_list_encodings() as $proxy) {
        $current = @mb_convert_encoding($mojibake, $proxy, 'UTF-8');
        if ($current === $expected) {
            echo "$proxy: match\n";
        }
    }
    
    (这会打印出
    wchar:match
    ;不确定这是什么意思。)


  • 是否有一个php函数可以从
    转到
    \xC3\xA2\xC2\xAC\xC2\xA6
    ?这似乎是第一次开始时遗漏的一步。否则答案很好!如果你的编辑器被配置为将文件保存为UTF-8,那么这两个字符串之间根本没有区别。我用两个十六进制编辑器(bless和wxHexEditor)尝试了这个方法,并检查了一个包含
    内容的文件。两个编辑器都显示了
    c3a2e282acc2a6
    。这对于
    来说是正确的(来自
    wchar
    )。我的例子是
    (来自
    Windows-1252
    )。
    // Source code saved as UTF-8
    $mojibake = "Z…Z";
    foreach (mb_list_encodings() as $proxy) {
        $original = mb_convert_encoding($mojibake, $proxy, 'UTF-8');
        echo $proxy, ': ', $original, PHP_EOL;
    }
    
    // Source code saved as UTF-8
    $mojibake = 'Z…Z';
    $expected = 'Z⬦Z';
    foreach (mb_list_encodings() as $proxy) {
        $current = @mb_convert_encoding($mojibake, $proxy, 'UTF-8');
        if ($current === $expected) {
            echo "$proxy: match\n";
        }
    }