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

Jas*_*ley 9 c# optimization character-encoding

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

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();
Run Code Online (Sandbox Code Playgroud)

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

例如,十进制中的中文字符为十六进制的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/1http://unicodelookup.com/#0x0069/1

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

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

更新(清洁版):

return Encoding.GetEncoding("ISO-8859-1").GetString(Encoding.GetEncoding(936).GetBytes(text));
Run Code Online (Sandbox Code Playgroud)

Eam*_*nne 10

好吧,对于一个,你不需要在调用之前将"内置"字符串表示转换为字节数组Encoding.Convert.

你可以这样做:

byte[] converted = Encoding.GetEncoding(936).GetBytes(text);
Run Code Online (Sandbox Code Playgroud)

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

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

我不会太担心效率; 你打算在收据打印机上打印多少MB /秒?

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

return Encoding.GetEncoding("Latin1").GetString(
           Encoding.GetEncoding(936).GetBytes(text)
       );
Run Code Online (Sandbox Code Playgroud)

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


Jon*_*eet 7

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

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

return Convert.ToBase64String(Encoding.GetEncoding(936).GetBytes(text));
Run Code Online (Sandbox Code Playgroud)

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

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