Я делаю инструмент (С#, WPF) для просмотра двоичных данных, которые могут содержать встроенный текст. Для таких пользователей данных традиционно использовать два вертикальных столбца, один из которых отображает шестнадцатеричное значение каждого байта, а другой - символ ASCII, соответствующий каждому байту, если он доступен для печати.
Я думал, что было бы неплохо поддерживать отображение встроенного текста с использованием кодировок, отличных от ASCII, в частности UTF-8 и UTF-16. Проблема в том, что кодовые точки UTF не отображают 1:1 с октетами. Я хотел бы сохранить выравнивание выходной сетки в соответствии с ее расположением в данных, поэтому мне нужно, чтобы каждый октет отображал что-то для отображения в соответствующей ячейке в сетке. Я думаю, что конечный октет каждой кодовой точки будет отображаться на получаемый символ Юникода и выводит карту байтов на заполнители, которые различаются по длине последовательности (возможно, кружили формы и используют цвет, чтобы отличать их от фактических закодированных символов), и продолжения и недопустимые байты аналогично заполнителям.
struct UtfOctetVisualization
{
enum Classification
{
Ascii,
NonAscii,
LeadByteOf2,
LeadByteOf3,
LeadByteOf4,
Continuation,
Error
}
Classification OctetClass;
int CodePoint; // valid only when OctetClass == Ascii or NonAscii
}
Метод Encoding.UTF8.GetString()
не предоставляет никакой информации о местоположении, из которого получен результирующий символ.
Я мог бы использовать Encoding.UTF8.GetDecoder()
и call Convert
передавать один байт за раз, чтобы completed
выходной параметр выдавал классификацию для каждого октета.
Но в обоих методах, чтобы иметь обработку недопустимых символов, мне нужно было бы реализовать класс DecoderFallback
? Это выглядит сложным.
Есть ли простой способ получить эту информацию с помощью API, поставляемых с.NET (в System.Text
или иначе)? Используя System.Text.Decoder
, как бы выглядел этот резервный образ, который заполняет выходной массив, разделяемый с декодером?
Или более возможно написать пользовательский распознаватель UTF-8 (конечный автомат)?
Как насчет декодирования одного символа за раз, чтобы вы могли захватить количество байтов, которое занимает каждый символ. Что-то вроде этого:
string data = "hello????";
byte[] buffer = new byte[Encoding.UTF8.GetByteCount(data)];
int bufferIndex = 0;
for(int i = 0; i < data.Length; i++)
{
int bytes = Encoding.UTF8.GetBytes(data, i, 1, buffer, bufferIndex);
Console.WriteLine("Character: {0}, Position: {1}, Bytes: {2}", data[i], i, bytes);
bufferIndex += bytes;
}
Fiddle: https://dotnetfiddle.net/poohHM
Те, которые? "В строке, должны быть многобайтными символами, но SO dosent позволяют мне вставлять их. См. Fiddle.
Я не делаю этого, это будет тренироваться так, как вы хотите, когда вы смешиваете двоичный файл с символами, как отметил @Jon. Я имею в виду, что вы что-то увидите, но, возможно, это не так, как вы ожидаете, потому что кодировщик не сможет отличить, какие байты должны быть символами.
6f 6f
означает «oo» или «潯»?