Мы можем упростить этот строковый код кодирования

Действительно ли возможно упростить этот код в более чистую/быстрее форму?

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));

9
задан svick 2 May 2012 в 07:17
поделиться

3 ответа

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 вместо этого (который почти идентичен). Вы можете попробовать рефлектор , чтобы увидеть, что он делает с вашей Системой. Последовательность, прежде чем он отправит его по проводу.

10
ответ дан 4 December 2019 в 10:32
поделиться

Почти все будет чище, чем это - вы действительно злоупотребляете текстом здесь, IMO. Вы пытаетесь представлять эффективно непрозрачные двоичные данные (закодированный текст) в виде текстовых данных ... так что вы потенциально получите такие вещи, как колокольники, ускользающие и т. Д.

Обычный способ кодирования непрозрачных двоичных данных в тексте является Base64 Таким образом, вы могли бы использовать:

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

Полученный текст будет полностью ASCII, который гораздо реже приведет к вам хлопот.

Редактировать: Если вам нужен этот выход, я настоятельно рекомендую, чтобы вы представляли его как массив байтового байта, а не в виде строки ... пропустите его в качестве байтового массива с этой точки, поэтому вы не соблазнены Выполните строковые операции на нем.

7
ответ дан 4 December 2019 в 10:32
поделиться

У вашего квитанции принтер имеет 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 - это полезная кодировка, когда вы хотите кодировать двоичные данные в строке, например, отправить через последовательный порт.

3
ответ дан 4 December 2019 в 10:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: