PHP';s utf8#U解码和C#';s Encoding.UTF8.GetString为同一输入返回不同的输出

PHP';s utf8#U解码和C#';s Encoding.UTF8.GetString为同一输入返回不同的输出,c#,php,utf-8,character-encoding,C#,Php,Utf 8,Character Encoding,我有一段PHP代码,它使用utf8_decode()将两个字节数组(一个有32个字节,另一个有70个字节)转换为UTF-8字符串: 然后我有了这个C代码,它使用Encoding.UTF8.GetString()做同样的事情: 首先,在C#中,两个字节数组在转换后产生相同的字符串,这与PHP不同。其次,与PHP相比,C#中的字符串是不同的 PHP中是否有一个函数在给定相同输入的情况下实际返回与C#的Encoding.UTF8.GetString()相同的输出?或者我遗漏了什么导致C#和PHP之间输

我有一段PHP代码,它使用utf8_decode()将两个字节数组(一个有32个字节,另一个有70个字节)转换为UTF-8字符串:

然后我有了这个C代码,它使用Encoding.UTF8.GetString()做同样的事情:

首先,在C#中,两个字节数组在转换后产生相同的字符串,这与PHP不同。其次,与PHP相比,C#中的字符串是不同的


PHP中是否有一个函数在给定相同输入的情况下实际返回与C#的Encoding.UTF8.GetString()相同的输出?或者我遗漏了什么导致C#和PHP之间输出不同的东西吗?

示例中的字节数组不是有效的UTF-8。基本上,如果你看到��� C#输出中的符号,意味着
编码.UTF8.GetString()
使用替换字符表示无法转换为输出字符的编码输入字节序列。查看更多详细信息

但是,您仍然可以在PHP中重现
Encoding.UTF8.GetString()
的相同行为:

$bytes32=[144204205119,77176172,140,110,162222255,14,38252,82118138,1301241451995516222480102141140,5719436];
$string32=\pack('C*',…$bytes32);
$string32Utf8=\mb_convert_编码($string32,'ASCII','UTF-8');
$bytes70=[239, 191, 189, 239, 191, 189, 239, 191, 189, 119, 77, 239, 191, 189, 239, 191, 189, 239, 191, 189, 110, 239, 191, 189, 239, 191, 189, 239, 191, 189, 14, 38, 239, 191, 189, 82, 118, 239, 191, 189, 239, 191, 189, 124, 239, 191, 189, 239, 191, 189, 55, 239, 191, 189, 239, 191, 189, 80, 102, 239, 191, 189, 239, 191, 189, 57, 239, 191, 189, 36];
$string70=\pack('C*',…$bytes70);
$string70Utf8=\mb\U转换编码($string70,'ASCII','UTF-8');
\变量转储($string32Utf8、$string70Utf8、$string32Utf8===$string70Utf8);
您可以在此处进行测试:

我做了一些不同的事情:

  • 由于字节数组表示UTF-8字符串,因此无法将其转换为二进制字符串。如
    chr
    函数文档中所述:

    此函数不知道任何字符串编码,尤其是不能传递Unicode代码点值以生成UTF-8或UTF-16等多字节编码的字符串

    另一方面,函数可以处理各种类型的二进制数据格式。
    \pack('C*',…$bytes32)
    意味着字节数组将被视为一个无符号字符序列并打包成二进制字符串

  • 函数的名称非常混乱;它的名称应该类似于
    utf8_to_iso88591
    ,因为这正是它所做的:

    将使用UTF-8编码的ISO-8859-1字符的字符串转换为单字节ISO-8859-1

    如果我们想复制
    Encoding.UTF8.GetString()
    示例,我们真正需要做的是将UTF-8编码的二进制字符串转换为ASCII。您可以使用函数来完成,就像这样:
    mb\u convert\u Encoding($utf8String,'ASCII,'UTF-8')

  • 希望这些评论能有所帮助

    $bytes32 = [144, 204, 205, 119, 77, 176, 172, 140, 110, 162, 222, 255, 14, 38, 252, 82, 118, 138, 130, 124, 145, 199, 55, 162, 224, 80, 102, 141, 140, 57, 194, 36];
    $string32 = implode(array_map("chr", $bytes32));
    $string32Utf8 = utf8_decode($string32);
    
    $bytes70 = [239, 191, 189, 239, 191, 189, 239, 191, 189, 119, 77, 239, 191, 189, 239, 191, 189, 239, 191, 189, 110, 239, 191, 189, 239, 191, 189, 239, 191, 189, 14, 38, 239, 191, 189, 82, 118, 239, 191, 189, 239, 191, 189, 124, 239, 191, 189, 239, 191, 189, 55, 239, 191, 189, 239, 191, 189, 80, 102, 239, 191, 189, 239, 191, 189, 57, 239, 191, 189, 36];
    $string70 = implode(array_map("chr", $bytes70));
    $string70Utf8 = utf8_decode($string70);
    
    echo '$string32Utf8: ' . $string32Utf8; // echoes ???wM???n??&?Rv??|??7??Pf??9?$
    echo '$string70Utf8: ' . $string70Utf8; // echoes ???wM???n???&?Rv??|??7??Pf??9?$
    echo '$string32Utf8 === $string70Utf8: ' . json_encode($string32Utf8 ===  $string70Utf8); // echoes false
    
    byte[] bytes32 = new byte[] { 144, 204, 205, 119, 77, 176, 172, 140, 110, 162, 222, 255, 14, 38, 252, 82, 118, 138, 130, 124, 145, 199, 55, 162, 224, 80, 102, 141, 140, 57, 194, 36 };
    string string32Utf8 = Encoding.UTF8.GetString(bytes32);
    
    byte[] bytes70 = new byte[] { 239, 191, 189, 239, 191, 189, 239, 191, 189, 119, 77, 239, 191, 189, 239, 191, 189, 239, 191, 189, 110, 239, 191, 189, 239, 191, 189, 239, 191, 189, 14, 38, 239, 191, 189, 82, 118, 239, 191, 189, 239, 191, 189, 124, 239, 191, 189, 239, 191, 189, 55, 239, 191, 189, 239, 191, 189, 80, 102, 239, 191, 189, 239, 191, 189, 57, 239, 191, 189, 36 };
    string string70Utf8 = Encoding.UTF8.GetString(bytes70);
    
    Console.WriteLine("string32Utf8: " + string32Utf8); // Writes ���wM���n���&�Rv��|��7��Pf��9�$
    Console.WriteLine("string70Utf8: " + string70Utf8); // Writes ���wM���n���&�Rv��|��7��Pf��9�$
    Console.WriteLine("string32Utf8 == string70Utf8: " + (string32Utf8 == string70Utf8)); // Writes true