c#UTF8 GetString from bytes数组不等于php chr函数

c#UTF8 GetString from bytes数组不等于php chr函数,c#,php,utf-8,character-encoding,C#,Php,Utf 8,Character Encoding,我想做一个解码器。Basic system.NET4.7我正在尝试将这个系统迁移到php中,但在转换字节时遇到了问题。就我所理解的C#上的默认字符串UTF-16le而言,我理解ord和chr函数在PHP端为UCS-2。我想做下面,我没有得到相同的结果有代码。我能做些什么来解决这个问题,提前谢谢 XOR Encoded Text Bytes = [101,107,217,78,40,68,234,218,162,67,139,81,44,166,24,148]; 在C# 在PHP上 for($i

我想做一个解码器。Basic system.NET4.7我正在尝试将这个系统迁移到php中,但在转换字节时遇到了问题。就我所理解的C#上的默认字符串UTF-16le而言,我理解ordchr函数在PHP端为UCS-2。我想做下面,我没有得到相同的结果有代码。我能做些什么来解决这个问题,提前谢谢

XOR Encoded Text Bytes = [101,107,217,78,40,68,234,218,162,67,139,81,44,166,24,148];
C#

在PHP上

for($i=0;$i<sizeof($encoded);$i++){
            echo "\t".$encoded[$i]." => ".chr($encoded[$i])."\n";
            $tmpStr .= chr($encoded[$i]);
        }
PHP结果大小=16:

ek�N(D�ڢC�Q,��
字符串看起来相同,但字节转换却截然不同

C#结果到字节数组:

byte[] utf8 = System.Text.Encoding.Unicode.GetBytes(result);
Console.WriteLine(string.Join("-", utf8));
回应= 101-0-107-0-253-255-78-0-40-0-68-0-253-255-162-6-67-0-253-255-81-0-44-0-253-255-24-0-253-255

PHP结果到字节数组:

echo implode("-",unpack("C*", $tmpStr));
响应=101-107-217-78-40-68-234-218-162-67-139-81-44-166-24-148

如果php响应转换为UTF-16le,结果也会不同

echo implode("-",unpack("C*", mb_convert_encoding($tmpStr,'UTF-16le')));
回应= 101-0-107-0-63-0-78-0-40-0-68-0-63-0-162-6-67-0-63-0-81-0-44-0-63-0-24-0-63-0


你在这里混合了完全不同的东西

首先,在C#代码中,当从字节转换为字符串,然后从字符串转换回字节时,使用的编码不同:
encoding.UTF8
在第一种情况下,使用的是
encoding.Unicode
(即
UTF-16
的.NET名称)。。。如果你这样做,事情就不会顺利。顺便说一下,我不确定PHP的
UCS2
是否等同于
UTF-16

  • 根据字符的不同,按1、2、3或4字节对字符进行编码
  • 根据字符的不同,按2或4字节对字符进行编码
  • 始终按2字节编码字符,因此编码字符不能超过65536个
那么,传递给“字节到字符串”转换的内容不一定有效!因为您对输入数据进行了异或运算(我假设它是某个秘密字符串),所以在某些编码中,结果字节可能是有效序列,也可能不是有效序列。例如:

  • 它在中无效,因为(在您的示例中)字节数>127
  • 它在
    UTF-8
    中无效,因为
    UTF-8
    不会将217后跟78识别为1、2、3或4字节字符;因此� 你看在N之前
  • 它似乎也是无效的
    UTF-16
    ,但是往返是有效的(我可以使用.NET的
    Unicode.GetString
    ,然后
    Unicode.GetBytes
    ,取回原始数组)。如果我删除了你的最后一个字节,并以奇数个字节结束,那么
    UTF-16
    往返就不再有效了
  • 虽然我没有测试它,但它也应该是无效的,因为对于2字节字符来说,
    UCS-2
    “看起来像”
    UTF-16
  • 往返可以使用编码,例如,因为这些编码接受任何字节。但是,我不鼓励使用这种技巧,因为您必须确保编码/解码过程的两侧使用相同的代码页
因此,我认为,在您的情况下,将XORed字节存储为字符串的最佳方法是将数组转换为base64。在C中,您可以这样做:

//下面的代码为您提供zwt1thiheiny+QydRLEIYMA==
var converted=Convert.tobase64字符串(数组);
//这一个返回初始数组
var bytes=Convert.FromBase64String(已转换);
快速谷歌搜索会告诉你在PHP中使用
base64\u编码
base64\u解码



底部注释:如果你想真正理解所有这些编码的内容,这里是关于这个主题的必读博文:

是的,如果两个系统都是我的,我可以将字节存储为base64,但是silverlight应用程序是用我用php重新设计了这个系统,以独立于de我用php调试了silverlight应用程序,我使用了密码的哈希函数,我想用php实现它,但我想在正确的xor加密后解决这个字节字符串。问题解决了@odalet感谢您的回答,问题自行解决:)。我没有对PHP代码做任何更改,只是将服务器的PHP版本从7.2升级到7.3。我害怕再次尝试删除PHP版本并保持原样:)。
echo implode("-",unpack("C*", $tmpStr));
echo implode("-",unpack("C*", mb_convert_encoding($tmpStr,'UTF-16le')));