вычисление 31-битного числа/игнорирование старшего бита

Я работаю над частью программного обеспечения, которое анализирует изображения битового потока E01. По сути, это файлы криминалистических данных, которые позволяют пользователю сжимать все данные на диске в один файл. Формат E01 включает данные об исходных данных, в том числе хэш MD5 исходных и результирующих данных и т. д. com/p/libewf/downloads/detail?name=Expert%20Witness%20Compression%20Format%20%28EWF%29.pdf" rel="nofollow">здесь. На мою проблему:

Файл e01 содержит раздел «таблица», который представляет собой серию 32-битных чисел, смещенных в другие места в файле e01, где расположены фактические фрагменты данных. Я успешно разобрал эти данные в список, выполнив следующие действия:

this.ChunkLocations = new List<int>();
//hack:Will this overflow?  We are adding to integers to a long?
long currentReadLocation = TableSectionDescriptorRef.OffsetFromFileStart + c_SECTION_DESCRIPTOR_LENGTH + c_TABLE_HEADER_LENGTH;
byte[] currReadBytes;
using (var fs = new FileStream(E01File.FullName, FileMode.Open))
      {
      fs.Seek(currentReadLocation, 0);
      for (int i = 0; i < NumberOfEntries; i++)
                {
                    currReadBytes = new byte[c_CHUNK_DATA_OFFSET_LENGTH];
                    fs.Read(currReadBytes,0, c_CHUNK_DATA_OFFSET_LENGTH);
                    this.ChunkLocations.Add(BitConverter.ToUInt32(currReadBytes, 0));
                }
       }

c_CHUNK_DATA_OFFSET_LENGTH составляет 4 байта/"32-битное" число.

Согласно спецификации ewf/e01, «старший бит в смещении данных фрагмента указывает, является ли фрагмент сжатым (1) или несжатым (0)». Об этом, по-видимому, свидетельствует тот факт, что, если я преобразую смещения в целые числа, в результатах будут большие отрицательные числа (без сомнения, для фрагментов без сжатия), но большинство других смещений кажутся правильно увеличенными, но каждый время от времени появляются сумасшедшие данные. Данные в ChunkLocations выглядят примерно так:

346256
379028
-2147071848
444556
477328
510100

Где с -2147071848 кажется, что старший бит был перевернут, чтобы указать сжатие/отсутствие сжатия.

ВОПРОСЫ: Итак, если MSB используется для обозначения наличия сжатия, то на самом деле я имею дело с 31-битным числом, верно?
1. Как игнорировать MSB/ вычислить 31-битное число при вычислении значение смещения?
2. Это кажется странным стандартом, поскольку может показаться, что он значительно ограничит размер возможных смещений, поэтому я спрашиваю, не упускаю ли я что-то? Эти смещения кажутся правильными, когда я перехожу к этим местам в файле e01.

Спасибо за любую помощь!


person rune711    schedule 06.01.2013    source источник
comment
С 31-битными смещениями вы можете адресовать до 2 ГБ.   -  person dtb    schedule 07.01.2013


Ответы (2)


Такие вещи типичны при работе с двоичными форматами. Как указал dtb, 31 бит, вероятно, достаточно много для этого приложения, поскольку оно может адресовать смещения до 2 ГиБ. Поэтому они используют этот дополнительный бит в качестве флага для экономии места.

Вы можете просто замаскировать бит с помощью побитового И:

const UInt32 COMPRESSED = 0x80000000;   // Only bit 31 on

UInt32 raw_value = 0x80004000;          // test value

bool compressed = (raw_value & COMPRESSED) > 0;
UInt32 offset = raw_value & ~COMPRESSED;

Console.WriteLine("Compressed={0}  Offset=0x{1:X}", compressed, offset);

Выход:

Compressed=True  Offset=0x4000
person Jonathon Reinhart    schedule 06.01.2013
comment
Ага, только что понял и исправил. Спасибо. - person Jonathon Reinhart; 07.01.2013
comment
Извините, но не могли бы вы объяснить, что такое 0x80000000? Это шестнадцатеричное значение MSB 32-битного целого числа без знака? Кроме того, меня беспокоят размеры смещения, потому что мы, безусловно, имеем дело с файлами E01 размером в терабайты, поэтому я не уверен, как это будет работать... Большое спасибо! - person rune711; 07.01.2013
comment
Да. Зайдите в калькулятор Windows, измените его на шестнадцатеричный и введите 0x80000000. Вы увидите, что включен только бит 31. - person Jonathon Reinhart; 07.01.2013
comment
Я предлагаю, чтобы, если вы собираетесь работать с таким двоичным форматом, вы очень ознакомились с шестнадцатеричным форматом. Это имеет больше смысла, чем wayyy, когда вы начинаете его использовать. Кроме того, хорошо познакомьтесь с маскированием и сдвигом целых чисел. - person Jonathon Reinhart; 07.01.2013
comment
Потрясающий. Спасибо. Последний вопрос... объясните, что такое оператор ~... Честно говоря, я никогда не сталкивался с таким! - person rune711; 07.01.2013
comment
Это побитовый оператор not. Он инвертирует все биты. Итак, 0x80000000 становится 0x7FFFFFFF. Чтобы замаскировать бит 31 выключенным, вы выполняете операцию И со входным значением со всеми битами, кроме одного включенного. В результате этот бит всегда выключен. - person Jonathon Reinhart; 07.01.2013
comment
На самом деле, почитайте. Это очень поможет вам. побитовые операторы C предоставляют массу информации. - person Jonathon Reinhart; 07.01.2013

Если вы просто хотите удалить начальный бит, выполните побитовое и (&) значения с 0x7FFFFFFFF

person OldProgrammer    schedule 06.01.2013