我们可以简化这个字符串编码代码

是否可以将此代码简化为更清晰/更快的forms?

StringBuilder builder = new StringBuilder(); var encoding = Encoding.GetEncoding(936); // convert the text into a byte array byte[] source = Encoding.Unicode.GetBytes(text); // convert that byte array to the new codepage. byte[] converted = Encoding.Convert(Encoding.Unicode, encoding, source); // take multi-byte characters and encode them as separate ascii characters foreach (byte b in converted) builder.Append((char)b); // return the result string result = builder.ToString(); 

简单地说,它需要一个带有中文字符的字符串,如郓,并将它们转换为ài。

例如,十进制中的中文字符为hex的37126或0x9106。

请参见http://unicodelookup.com/#0x9106/1

转换为字节数组,得到[145,6](145 * 256 + 6 = 37126)。 当在CodePage 936(简体中文)中编码时,我们得到[224,105]。 如果我们将这个字节数组分解成单个字符,我们224 = e0 =à并且105 = 69 = i在unicode中。

请参见http://unicodelookup.com/#0x00e0/1和http://unicodelookup.com/#0x0069/1

因此,我们正在进行编码转换,并确保输出Unicode字符串中的所有字符都可以使用最多两个字节来表示。

更新:我需要这个最终表示,因为这是我的收据打印机接受的格式。 让我永远想通了! :)由于我不是编码专家,我正在寻找更简单或更快的代码,但输出必须保持不变。

更新(清洁版):

 return Encoding.GetEncoding("ISO-8859-1").GetString(Encoding.GetEncoding(936).GetBytes(text)); 

好吧,首先,在调用Encoding.Convert之前,您不需要将“内置”字符串表示转换为字节数组。

你可以这样做:

 byte[] converted = Encoding.GetEncoding(936).GetBytes(text); 

然后从该字节数组重建一个字符串,从而char值直接映射到字节,你可以做…

 static string MangleTextForReceiptPrinter(string text) { return new string( Encoding.GetEncoding(936) .GetBytes(text) .Select(b => (char) b) .ToArray()); } 

我不会太担心效率; 无论如何你要在收据打印机上打印多少MB /秒?

Joe指出,有一种编码可以直接将字节值0-255映射到代码点,而且它是古老的Latin1 ,它允许我们将函数缩短为……

 return Encoding.GetEncoding("Latin1").GetString( Encoding.GetEncoding(936).GetBytes(text) ); 

顺便说一下,如果这是一个有缺陷的Windows专用API(它的外观,它的外观),你可能正在处理代码页1252 (几乎相同)。 您可以尝试使用reflection器来查看它在通过线路发送之前对System.String执行的操作。

几乎所有东西都比这更干净 – 你真的在这里滥用文字,IMO。 您试图将有效的不透明二进制数据(编码文本)表示为文本数据…因此您可能会获得诸如铃声字符,转义等内容。

在文本中编码不透明二进制数据的常规方法是base64,因此您可以使用:

 return Convert.ToBase64String(Encoding.GetEncoding(936).GetBytes(text)); 

生成的文本将完全是ASCII,这不太可能导致您麻烦。

编辑:如果您需要该输出,我强烈建议您将其表示为字节数组而不是字符串…从那时起将其作为字节数组传递,因此您不必尝试执行字符串操作在上面。

您的收据打印机是否有接受字节数组而不是字符串的API? 如果是这样,您可以使用收据打印机使用的编码将代码简化为单个转换,从Unicode字符串到字节数组。

此外,如果要将字节数组转换为字符值对应于字节值的字符串的字符串,则可以使用代码页28591 aka Latin1 aka ISO-8859-1。

即,以下

 foreach (byte b in converted) builder.Append((char)b); string result = builder.ToString(); 

可以替换为:

 // All three of the following are equivalent // string result = Encoding.GetEncoding(28591).GetString(converted); // string result = Encoding.GetEncoding("ISO-8859-1").GetString(converted); string result = Encoding.GetEncoding("Latin1").GetString(converted); 

当您想要在字符串中编码二进制数据时,例如通过串行端口发送,Latin1是一种有用的编码。