Существует ли тип кодировки .NET, который будет возвращать каждый байт в базовом файле как символ с тем же порядковым значением? - PullRequest
2 голосов
/ 11 июля 2011

Это мой вопрос:

Существует ли объект / тип кодировки .NET, который будет декодировать каждый байт в файле до символа с точно таким же порядковым значением, как и в файле, в основном выполняется сопоставление 1: 2 между байтом в подать порядковый номер символа?

Подробнее

Я читаю текстовые данные, которые содержат некоторые двоичные значения, т.е. целое число, закодированное как 4 байта. Данные должны быть прочитаны через TextReader-класс, потому что я получаю их из стандартного вывода внешних программ. Данные, которые я получаю, иногда искажаются из-за проблем с кодированием. По сути, потоки .NET декодируют данные из внешней программы и иногда отключают символ, так что какое бы ни было порядковое значение байта / символа, выводимое внешней программой, не совпадает с тем, которое я прочитал в .NET.

Справочная информация

Я общаюсь с внешней программой Mercurial по стандартному вводу / выводу, и по какой-то причине они решили вывести некоторые данные в двоичном виде.

Протокол выглядит так:

<type:single-byte char><length:32-bit integer><data:string>

Тип - это однобайтовый символ, который просто сообщает мне, является ли это выводом ошибки, стандартным выводом или результатом выполнения команды.

Длина представляет собой 32-разрядное целое число, выводится в виде 4 байтов в потоке.

Данные представляют собой строку, состоящую из последовательности байтов вышеупомянутой длины, но эти символы могут быть закодированы с использованием кодировки по умолчанию Mercurial.

Например, если я попрошу Mercurial использовать кодировку кодовой страницы 1252 (стандартная Windows), тогда строка будет закодирована в этой кодировке.

Однако вот в чем проблема: длина не будет, конечно,

Если я настрою объект .NET Process для использования Windows-1252 в качестве кодировки для потока StandardOutput, например:

psi.StandardOutputEncoding = Encoding.GetEncoding("Windows-1252");
psi.StandardErrorEncoding = Encoding.GetEncoding("Windows-1252");

Затем в какой-то момент декодирование данных от клиента перестает синхронизироваться, потому что одно из двоичных значений длины в итоге было декодировано и, таким образом, имеет порядковый номер, отличный от байта из файла.

Мой текущий пример содержал символ евро в некоторый момент (как печатный символ), однако байт из файла не имел значения 172, которое было значением печатного символа. Некоторая расшифровка произошла.

Однако, допустим, у меня есть файл, содержащий каждое возможное значение байта.

Затем я открываю файл через одного из потомков TextReader и указываю кодировку.

Есть ли какая-либо кодировка, которая позволит мне использовать метод TextReader.Read() и читать каждый байт из этого файла без изменений?

По сути, мой цикл декодирования выглядит следующим образом:

read one byte, convert to character
if character is 'r', 'e' or 'o':
    read next 4 bytes, assemble to integer
    read next X bytes (x=integer above)
    decode the bytes to a string using the encoding specified

Однако я попробовал это, и оно отключилось, когда длина содержала символ евро (как печатный символ). Очевидно, этот символ имел одно байтовое значение в файле, но был декодирован как другой.

Итак, подведем итог:

Существует ли объект / тип кодировки .NET, который будет декодировать каждый байт в файле до символа с точно таким же порядковым значением, что и в файле, в основном "без кодировки"?

1 Ответ

4 голосов
/ 11 июля 2011

Правильное кодирование - «iso-8859-1», оно декодирует каждый байт в один и тот же порядковый номер символа. Очевидно, это также только такая кодировка, присутствующая в .NET (по крайней мере, на моем компьютере), которая имеет эту возможность / функцию.

Я написал тестовую программу LINQPad , чтобы выяснить это:

void Main()
{
    byte[] buffer = new byte[256];
    for (int index = 0; index < 256; index++)
        buffer[index] = (byte)index;

    foreach (var encodingInfo in Encoding.GetEncodings())
    {
        string s = encodingInfo.GetEncoding().GetString(buffer);
        var stream = new MemoryStream(buffer);
        var reader = new StreamReader(stream, encodingInfo.GetEncoding());
        bool equal = true;
        for (int index = 0; index < 256; index++)
            if (reader.Read() != index)
            {
                equal = false;
                break;
            }
        if (equal)
            Debug.WriteLine(encodingInfo.Name);
    }
}
...