Мне не нравится BitConverter
, потому что (как ответил Марк Гравелл) предполагается, что он полагается на системный порядок байтов, то есть технически вы должны выполнять проверку системного порядкового номера каждый раз, когда используете BitConverter
, чтобы убедиться, что вам не нужноперевернуть массив.Как правило, с сохраненными файлами вы обычно знаете порядок байтов, который вы пытаетесь прочитать, и это может не совпадать.Возможно, вы просто обрабатываете форматы файлов со значениями с прямым порядком байтов, например, в виде фрагментов PNG.
Из-за этого я просто написал собственные методы для этого, которые принимают байтовый массив, чтениесмещение и чтение длины в качестве аргументов, а также логическое значение для указания обработки порядка байтов, которое использует сдвиг битов для эффективности:
public static UInt64 ReadIntFromByteArray(Byte[] data, Int32 startIndex, Int32 bytes, Boolean littleEndian)
{
Int32 lastByte = bytes - 1;
if (data.Length < startIndex + bytes)
throw new ArgumentOutOfRangeException("startIndex", "Data array is too small to read a " + bytes + "-byte value at offset " + startIndex + ".");
UInt64 value = 0;
for (Int32 index = 0; index < bytes; index++)
{
Int32 offs = startIndex + (littleEndian ? index : lastByte - index);
value += (UInt64)(data[offs] << (8 * index));
}
return value;
}
Этот код может обрабатывать любое значение от 1 до 8 байтов, оба малопорядок байтовЕдинственная небольшая особенность использования заключается в том, что вам нужно дать оба байта для чтения, и нужно специально привести результат к нужному типу.
Пример из некоторого кода, где яиспользовал его, чтобы прочитать заголовок некоторого проприетарного типа изображения:
Int16 imageWidth = (Int16) ReadIntFromByteArray(fileData, hdrOffset, 2, true);
Int16 imageHeight = (Int16) ReadIntFromByteArray(fileData, hdrOffset + 2, 2, true);
Это будет читать два последовательных 16-битных целых числа из массива в виде значений со знаком с прямым порядком байтов.Конечно, вы можете просто сделать несколько функций перегрузки для всех возможностей, например:
public Int16 ReadInt16FromByteArrayLe(Byte[] data, Int32 startIndex)
{
return (Int16) ReadIntFromByteArray(data, startIndex, 2, true);
}
Но лично я не стал этим заниматься.
И вот то же самое для написаниябайт:
public static void WriteIntToByteArray(Byte[] data, Int32 startIndex, Int32 bytes, Boolean littleEndian, UInt64 value)
{
Int32 lastByte = bytes - 1;
if (data.Length < startIndex + bytes)
throw new ArgumentOutOfRangeException("startIndex", "Data array is too small to write a " + bytes + "-byte value at offset " + startIndex + ".");
for (Int32 index = 0; index < bytes; index++)
{
Int32 offs = startIndex + (littleEndian ? index : lastByte - index);
data[offs] = (Byte) (value >> (8*index) & 0xFF);
}
}
Единственное требование здесь заключается в том, что вы должны приводить входной аргумент к 64-битному целому числу без знака при передаче его функции.