Ole*_*ych -1 delphi character-encoding
我从物理设备读取用户名。所有用户名都是带有西里尔符号的 Base64 编码字符串。不知何故,设备错误地将符号转换为 utf8,所以我尝试在客户端修复它,以在 GUI 中显示正确的用户名。
\n问题是部分用户名转换成功,但当我尝试这样做时,某些部分会引发异常。
\n这是我如何做到这一点的简化示例:
\nprocedure TForm3.Button1Click(Sender: TObject);\n\n function Convert(ABase64String : string) : string;\n begin\n var xWin1251 := TEncoding.GetEncoding(1251);\n try\n var DecodedStr : string := TNetEncoding.Base64String.Decode(ABase64String);\n var DecodedBytes := TEncoding.UTF8.GetBytes(DecodedStr);\n var ConvertedBytes := TEncoding.Convert(TEncoding.UTF8, xWin1251, DecodedBytes);\n\n Result := TEncoding.UTF8.GetString(ConvertedBytes);\n finally\n xWin1251.Free;\n end;\n end;\n\nconst\n s1 = '0KDRmtCg0ZHQodCD0KHQi9Cg0ZQg0KDRmtCg0ZHQoNGU0KDRldCgwrvQoMKwIA==';\n s2 = '0KDigJjQodGT0KDCttCg0ZHQoNCF0KHQitCh0IPQoNGU0KHigJMg0KDRmtCh4oCT0KE=';\nbegin\n ShowMessage(Convert(s1));\n ShowMessage(Convert(s2));\nend;\nRun Code Online (Sandbox Code Playgroud)\ns1- 转换得很好。
调试值:
\nDecodedStr '\xd0\xa0\xd1\x9a\xd0\xa0\xd1\x91\xd0\xa1\xd0\x83\xd0\xa1\xd0\x8b\xd0\xa0\xd1\x94 \xd0\xa0\xd1\x9a\xd0\xa0\xd1\x91\xd0\xa0\xd1\x94\xd0\xa0\xd1\x95\xd0\xa0\xc2\xbb\xd0\xa0\xc2\xb0 '\nDecodedBytes (208, 160, 209, 154, 208, 160, 209, 145, 208, 161, 208, 131, 208, 161, 208, 139, 208, 160, 209, 148, 32, 208, 160, 209, 154, 208, 160, 209, 145, 208, 160, 209, 148, 208, 160, 209, 149, 208, 160, 194, 187, 208, 160, 194, 176, 32)\nConvertedBytes (208, 156, 208, 184, 209, 129, 209, 142, 208, 186, 32, 208, 156, 208, 184, 208, 186, 208, 190, 208, 187, 208, 176, 32)\nResult '\xd0\x9c\xd0\xb8\xd1\x81\xd1\x8e\xd0\xba \xd0\x9c\xd0\xb8\xd0\xba\xd0\xbe\xd0\xbb\xd0\xb0 '\nRun Code Online (Sandbox Code Playgroud)\ns2- 使用消息引发异常No mapping for the Unicode character exists in the target multi-byte code page而不是返回值\xd0\x91\xd1\x83\xd0\xb6\xd0\xb8\xd0\xbd\xd1\x8c\xd1\x81\xd0\xba\xd1\x96 \xd0\x9c\xd1\x96\xd0\xa1。
调试值:
\nDecodedStr '\xd0\xa0\xe2\x80\x98\xd0\xa1\xd1\x93\xd0\xa0\xc2\xb6\xd0\xa0\xd1\x91\xd0\xa0\xd0\x85\xd0\xa1\xd0\x8a\xd0\xa1\xd0\x83\xd0\xa0\xd1\x94\xd0\xa1\xe2\x80\x93 \xd0\xa0\xd1\x9a\xd0\xa1\xe2\x80\x93\xd0\xa1'\nDecodedBytes (208, 160, 226, 128, 152, 208, 161, 209, 147, 208, 160, 194, 182, 208, 160, 209, 145, 208, 160, 208, 133, 208, 161, 208, 138, 208, 161, 208, 131, 208, 160, 209, 148, 208, 161, 226, 128, 147, 32, 208, 160, 209, 154, 208, 161, 226, 128, 147, 208, 161)\nConvertedBytes (208, 145, 209, 131, 208, 182, 208, 184, 208, 189, 209, 140, 209, 129, 208, 186, 209, 150, 32, 208, 156, 209, 150, 209)\nRun Code Online (Sandbox Code Playgroud)\n我发现处理文本编码的旧程序。它可以通过名为 的操作很好地转换所有值UTF8->WIN,所以我绝对知道这是可能的。
我错过了什么?
\n我试了一下你的数据,你的解码代码是正确的。
\n您所获得的 base64 解码为 UTF-8 字节,然后必须将其解码为 UTF-16,然后重新编码为 Windows-1251,然后必须解释生成的字节为 UTF-8 而不是 Windows-1251 。
\n您的Convert()函数正是这样做的 - 尽管您不需要第一次TEncoding.UTF8.GetBytes()调用,因为 base64 解码为 UTF-8 (Base64String.Decode()返回 UTF-16 字符串时假定为 UTF-8),因此您可以完全省略该步骤,例如:
function Convert(ABase64String : string) : string;\nbegin\n var xWin1251 := TEncoding.GetEncoding(1251);\n try\n //var DecodedStr : string := TNetEncoding.Base64String.Decode(ABase64String);\n //var DecodedBytes := TEncoding.UTF8.GetBytes(DecodedStr);\n var DecodedBytes := TNetEncoding.Base64.DecodeStringToBytes(ABase64String);\n\n var ConvertedBytes := TEncoding.Convert(TEncoding.UTF8, xWin1251, DecodedBytes);\n Result := TEncoding.UTF8.GetString(ConvertedBytes);\n finally\n xWin1251.Free;\n end;\nend;\nRun Code Online (Sandbox Code Playgroud)\n现在,话虽如此,这种方法非常适合您的第一个示例 Unicode 字符串'\xd0\x9c\xd0\xb8\xd1\x81\xd1\x8e\xd0\xba \xd0\x9c\xd0\xb8\xd0\xba\xd0\xbe\xd0\xbb\xd0\xb0 ',因为该字符串的 base64 是正确的。
对于第二个示例 Unicode 字符串'\xd0\x91\xd1\x83\xd0\xb6\xd0\xb8\xd0\xbd\xd1\x8c\xd1\x81\xd0\xba\xd1\x96 \xd0\x9c\xd1\x96\xd0\xa1',这种方法几乎完美地工作。实际上,base64 数据可以正确解码上述字符'\xd0\x91\xd1\x83\xd0\xb6\xd0\xb8\xd0\xbd\xd1\x8c\xd1\x81\xd0\xba\xd1\x96 \xd0\x9c\xd1\x96',但是最后一个字符'\xd0\xa1'(通常以 UTF-8 编码为字节$D0 $A1)的 base64 被解码为单个字节$D1而不是 2 个字节$D0 $A1。这就是为什么你从最终的结果中得到“无映射”错误的原因TEncoding.UTF8.GetString()。
所以,这不是你的解码代码中的错误 - 你只是解码错误的输入从一开始就
\n上述方案下Unicode 字符串的正确base64应该是'\xd0\x91\xd1\x83\xd0\xb6\xd0\xb8\xd0\xbd\xd1\x8c\xd1\x81\xd0\xba\xd1\x96 \xd0\x9c\xd1\x96\xd0\xa1':
'0KDigJjQodGT0KDCttCg0ZHQoNCF0KHQitCh0IPQoNGU0KHigJMg0KDRmtCh4oCT0KDQjg=='
不是:
\n'0KDigJjQodGT0KDCttCg0ZHQoNCF0KHQitCh0IPQoNGU0KHigJMg0KDRmtCh4oCT0KE='
(即,DQjg==代替E=在最后)
因此,无论是谁向您发送 Base64,这都是一个错误。正确的解决方案是修复 base64 的来源,而不是修复您的解码器(因为它没有损坏)。
\n| 归档时间: |
|
| 查看次数: |
196 次 |
| 最近记录: |