Использование неправильной кодировки при записи в файл C #

2

Я создаю двоичный файл для передачи третьей стороне, содержащей изображения и информацию о каждом изображении. Файл использует формат длины записи, поэтому каждая запись является определенной длиной. Начало каждой записи - индикатор длины записи, длина которого составляет 4 символа и представляет длину записи в формате Big Endian.

Я использую BinaryWriter для записи в файл, а для индикатора длины записи я использую Encoding.Default.

Проблема, с которой я столкнулась, состоит в том, что в одной записи есть один символ, который отображается как "?" потому что он непризнан. Моим алгоритмом для построения строки для индикатора длины записи является следующее:

  private string toBigEndian(int value)
    {
        string returnValue = "";            
        string binary = Convert.ToString(value, 2).PadLeft(32, '0');
        List<int> binaryBlocks = new List<int>();
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(0, 8), 2));
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(8, 8), 2));
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(16, 8), 2));
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(24, 8), 2));

        foreach (int block in binaryBlocks)
        {                
            returnValue += (char)block;
        }

        Console.WriteLine(value);

        return returnValue;
    }

Он берет длину записи, преобразует ее в 32-битный двоичный код, преобразует ее в куски 8-битного двоичного кода, а затем преобразует каждый кусок в соответствующий символ. Строка, возвращаемая здесь, содержит правильные символы, но когда она записывается в файл, один символ непризнан. Вот как я его пишу:

//fileWriter is BinaryWriter and record is Encoding.Default
fileWriter.Write(record.GetBytes(toBigEndian(length)));

Возможно, я использую неправильный тип кодирования? Я пробовал UTF-8, который должен работать, но иногда он дает дополнительные символы.

Заранее благодарим за помощь.

  • 0
    Какой персонаж не конвертирует должным образом?
  • 0
    Поскольку значение приводится к символу, а затем кодируется, как если бы оно было реальным символом, существует целый диапазон значений, которые не работают должным образом. Большинство значений выше 127, вероятно, будет неправильно ...
Теги:
character-encoding

4 ответа

6
Лучший ответ

Проблема заключается в том, что вы не должны возвращать значение как строку вообще.

Когда вы передаете значение в char, а затем кодируете его как 8-битные символы, есть несколько значений, которые будут закодированы в неправильный байтовый код и несколько значений, которые вообще не будут закодированы (в результате в символах?). Единственный способ не потерять данные на этом шаге - это кодировать его как UTF-16, но это даст вам восемь байтов вместо четырех.

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

private byte[] toBigEndian(int value) {
   byte[] result = BitConverter.GetBytes(value);
   if (BitConverter.IsLittleEndian) Array.Reverse(result);
   return result;
}

fileWriter.Write(toBigEndian(length));
  • 0
    Точно исправил и решил проблему. Спасибо.
1

Если вам действительно нужны бинарные четыре байта (т.е. не только четыре символа, но и 32-разрядное значение большого числа), тогда вы хотите что-то вроде этого:

byte[] bytes = new byte[4];
bytes[3] = (byte)((value >> 24) & 0xff);
bytes[2] = (byte)((value >> 16) & 0xff);
bytes[1] = (byte)((value >> 8) & 0xff);
bytes[0] = (byte)(value & 0xff);
fileWriter.Write(bytes);
1

Не создавайте строку из int для записи байтов. Лучше попробуйте следующее:

byte[] result = 
    {
      (byte)( value >> 24 ),
      (byte)( value >> 16 ),
      (byte)( value >> 8 ) ,
      (byte)( value >> 0 )
    };
0

Для чтения/записи битов из двоичных потоков с соответствующей энтерианностью используйте класс BitConverter, поскольку он имеет явную поддержку endianess: http://msdn.microsoft.com/en-us/library/system.bitconverter.islittleendian.aspx

Преобразование в двоичный код, а затем токенизация в байты, я должен сказать, самый неортодоксальный способ, который я вижу:)

  • 0
    Свойство IsLittleEndian предназначено только для чтения и сообщает вам, является ли система большой или мало порядковой. Это не позволяет вам установить порядок байтов. Для этого вам нужно бросить свой собственный или взять один из многих найденных в Интернете.
  • 0
    BitConverter не поддерживает порядковый номер. Это свойство будет указывать только на текущую платформу с прямым порядком байтов или нет. Это не сделает преобразование в big endian для вас.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню