Действительно ли возможно упростить этот код в более чистую/быстрее форму?
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.
Например, тот китайский символ в десятичном числе 37126 или 0x9106 в шестнадцатеричном числе.
См. http://unicodelookup.com/#0x9106/1
Преобразованный в массив байтов, мы добираемся [145, 6] (145 * 256 + 6 = 37126). При кодировании в Кодовой странице 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));
bstr = '0000 0100 1000 1101'.replace(' ', '')
hstr = '%0*X' % ((len(bstr) + 3) // 4, int(bstr, 2))
-121--1086809- Я частично отношусь к Eventum by MySQL . Свободный, легкий, настраиваемый, и я использовал его почти во всех своих проектах.
-121--3603943- Для одного из них не требуется преобразовывать «встроенное» представление последовательности в массив байтов перед вызовом Encoding.Convert
.
Вы могли бы просто сделать:
byte[] converted = Encoding.GetEncoding(936).GetBytes(text);
Чтобы затем восстановить последовательность из этого массива байтов, посредством чего значения символов непосредственно сопоставляются с байтами, вы могли бы сделать...
static string MangleTextForReceiptPrinter(string text) {
return new string(
Encoding.GetEncoding(936)
.GetBytes(text)
.Select(b => (char) b)
.ToArray());
}
Я бы не слишком беспокоился об эффективности; Сколько МБ/с вы собираетесь печатать на принтере для квитанций?
Джо указал, что существует кодировка, которая напрямую сопоставляет значения байтов 0-255 с кодовыми точками, и она устаревшая Latin1 , которая позволяет нам сократить функцию до...
return Encoding.GetEncoding("Latin1").GetString(
Encoding.GetEncoding(936).GetBytes(text)
);
По пути, если это API только для окон (который он, по виду), вы может иметь дело с кодовая страница 1252 вместо этого (который почти идентичен). Вы можете попробовать рефлектор , чтобы увидеть, что он делает с вашей Системой. Последовательность, прежде чем он отправит его по проводу.
Почти все будет чище, чем это - вы действительно злоупотребляете текстом здесь, IMO. Вы пытаетесь представлять эффективно непрозрачные двоичные данные (закодированный текст) в виде текстовых данных ... так что вы потенциально получите такие вещи, как колокольники, ускользающие и т. Д.
Обычный способ кодирования непрозрачных двоичных данных в тексте является Base64 Таким образом, вы могли бы использовать:
return Convert.ToBase64String(Encoding.GetEncoding(936).GetBytes(text));
Полученный текст будет полностью ASCII, который гораздо реже приведет к вам хлопот.
Редактировать: Если вам нужен этот выход, я настоятельно рекомендую, чтобы вы представляли его как массив байтового байта, а не в виде строки ... пропустите его в качестве байтового массива с этой точки, поэтому вы не соблазнены Выполните строковые операции на нем.
У вашего квитанции принтер имеет API, который принимает байтовый массив, а не строка? Если это так, что вы сможете упростить код с одной конверсией, из строки Unicode в байтовый массив, используя кодировку, используемую принтер квитанции.
Кроме того, если вы хотите преобразовать массив байтов в строку, значения символов, чьи значения символов соответствуют значениям байтов, вы можете использовать код Page 28591 aka latin1 aka iso-8859-1.
I.e. Следующие
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 - это полезная кодировка, когда вы хотите кодировать двоичные данные в строке, например, отправить через последовательный порт.