C#字符串编码转码有关问题
C#字符串编码转码问题
C#。在WPF中有个字符串变量a,需要把字符串的内容从Unicode转UTF-8,这样可以支持中文。要把这个转码后的字符串传入C++编的DLL中处理。现在是情况如下:
1.字符串的内容为“中.mp4”,转码后发现会把‘中’和‘.’转到一起了,在DLL中打印出来就是错的,会乱码。转成UTF-8的十六进制为:e4 b8 3f 6d 70 34
2.字符串的内容为“中文.mp4”,转码正确,显示无误。转成UTF-8的十六进制为:e4 b8 ad e6 96 87 2e 6d 70 34
也就是说当汉字为奇数出现时会转错,汉字为偶数出现时就不会转错。很奇怪。有大神知道吗?求帮助。。。
以下是我在C#中转码的部分,参数str就是我需要转码的字符串。

------解决思路----------------------
因为不是所有的字节串都可以转换为字符串,你的问题就是错误地用字符串来表示字节串。
详细解释:
当你调用dll函数WideCharToMultiByte的时候,封送StringBuilder用的是Ansi编码。
Ansi编码在不同的机器上是不同的,如果你的Windows是中文版,那么你的编码是CP936,大致等同于GB2312。
GB2312的编码用一个字节(<128)来表示英文字母数字等,用两个字节(两个都大于128)来表示汉字等。
但是用UTF8表示‘中'的时候,需要3个字节(e4 b8 ad),因此调用WideCharToMultiByte,转换’中.mp4‘返回了
e4 b8 ad 2e 6d 70 34。由于你错误的用了字符串去接受字节串,字节串要按Ansi方式放到StringBuilder里面。
e4 b8凑巧变成一个字,ad 2e却出现转换错误,因为GB2312中,如果第一个字节>128,第二个字节就必须大于128。转换错误的结果就是ad 2e变成了问号?(就是你看到的那个3f ),最终结果是e4 b8 3f 6d 70 34
当你转换’中文..mp4‘的时候,WideCharToMultiByte给你e4 b8 ad e6 96 87 2e
6d 70 34被GB2312解释为e4 b8 ad e6 96 87 2e 6d 70 34,恰巧没有违背GB2312的编码规定。
这就是你感觉单数出问题,双数不出问题的原因(运气而已)。
总而言之,不能盲目的在使用字节串的地方用字符串。
你的情况可以这样改正:
1、如果字节串(char*)用在函数调用里,用byte[]表示。
2、如果字节串(char*)用在结构里,用IntPtr表示。
3、转换的时候不用WideCharToMultiByte,而用dotnet的Encoding.UTF8.GetBytes。
C#。在WPF中有个字符串变量a,需要把字符串的内容从Unicode转UTF-8,这样可以支持中文。要把这个转码后的字符串传入C++编的DLL中处理。现在是情况如下:
1.字符串的内容为“中.mp4”,转码后发现会把‘中’和‘.’转到一起了,在DLL中打印出来就是错的,会乱码。转成UTF-8的十六进制为:e4 b8 3f 6d 70 34
2.字符串的内容为“中文.mp4”,转码正确,显示无误。转成UTF-8的十六进制为:e4 b8 ad e6 96 87 2e 6d 70 34
也就是说当汉字为奇数出现时会转错,汉字为偶数出现时就不会转错。很奇怪。有大神知道吗?求帮助。。。
以下是我在C#中转码的部分,参数str就是我需要转码的字符串。
private string ConvertToMutiByte(string str)
{
int i = 0;
i = WideCharToMultiByte(65001, 0, str, -1, null, 0, IntPtr.Zero, IntPtr.Zero);
StringBuilder MultiByte = new StringBuilder(i);
WideCharToMultiByte(65001, 0, str, -1, MultiByte, i, IntPtr.Zero, IntPtr.Zero);
string s = MultiByte.ToString();
return s;
}
------解决思路----------------------
因为不是所有的字节串都可以转换为字符串,你的问题就是错误地用字符串来表示字节串。
详细解释:
当你调用dll函数WideCharToMultiByte的时候,封送StringBuilder用的是Ansi编码。
Ansi编码在不同的机器上是不同的,如果你的Windows是中文版,那么你的编码是CP936,大致等同于GB2312。
GB2312的编码用一个字节(<128)来表示英文字母数字等,用两个字节(两个都大于128)来表示汉字等。
但是用UTF8表示‘中'的时候,需要3个字节(e4 b8 ad),因此调用WideCharToMultiByte,转换’中.mp4‘返回了
e4 b8 ad 2e 6d 70 34。由于你错误的用了字符串去接受字节串,字节串要按Ansi方式放到StringBuilder里面。
e4 b8凑巧变成一个字,ad 2e却出现转换错误,因为GB2312中,如果第一个字节>128,第二个字节就必须大于128。转换错误的结果就是ad 2e变成了问号?(就是你看到的那个3f ),最终结果是e4 b8 3f 6d 70 34
当你转换’中文..mp4‘的时候,WideCharToMultiByte给你e4 b8 ad e6 96 87 2e
6d 70 34被GB2312解释为e4 b8 ad e6 96 87 2e 6d 70 34,恰巧没有违背GB2312的编码规定。
这就是你感觉单数出问题,双数不出问题的原因(运气而已)。
总而言之,不能盲目的在使用字节串的地方用字符串。
你的情况可以这样改正:
1、如果字节串(char*)用在函数调用里,用byte[]表示。
2、如果字节串(char*)用在结构里,用IntPtr表示。
3、转换的时候不用WideCharToMultiByte,而用dotnet的Encoding.UTF8.GetBytes。