Доступ к конкретной двоичной информации на основе документации двоичного формата - PullRequest
0 голосов
/ 17 ноября 2011

У меня есть двоичный файл и документация формата, в котором хранится информация. Я пытаюсь написать простую программу, использующую c ++, которая извлекает определенную часть информации из файла, но я что-то упускаю, так как вывод isn не то, что я ожидаю.

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

<b>Half-word</b>   <b>Field Name</b>          <b>Type</b>    <b>Units</b>   <b>Range</b>       <b>Precision</b>
10          Block Divider       INT*2   N/A     -1          N/A
11-12       Latitude            INT*4   Degrees -90 to +90  0.001

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

Мой код:

#include <cstdlib>
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char* argv[])
{
  char* dataFileLocation = "testfile.bin";

  ifstream dataFile(dataFileLocation, ios::in | ios::binary);

  if(dataFile.is_open())
  {
    char* buffer = new char[32768];
    dataFile.seekg(10, ios::beg);
    dataFile.read(buffer, 4);
    dataFile.close();

    cout << "value is << (int)(buffer[0] & 255);
  }
}

Результатом является "значение равно 226", которое находится за пределами допустимого диапазона.

Я довольно новичок в этом, и вот каковы мои намерения при написании приведенного выше кода:

  1. Открыть файл в двоичном режиме
  2. Поиск в 11-м байте от начала файла
  3. Считать 4 байта с этой точки
  4. Закрыть файл
  5. Вывести эти 4 байта как целое число.

Если бы кто-то мог указать, где я иду не так, я бы это оценил. Я на самом деле не понимаю (buffer [0] & 255) часть (взяла это из некоторого примера кода), поэтому условия для неспециалистов за это будут высоко оценены.

Шестнадцатеричный дамп первых 100 байтов:

testfile.bin  98,402 bytes   11/16/2011   9:01:52
          -0 -1 -2 -3  -4 -5 -6 -7  -8 -9 -A -B  -C -D -E -F

00000000- 00 5F 3B BF  00 00 C4 17  00 00 00 E2  2E E0 00 00 [._;.............]
00000001- 00 03 FF FF  00 00 94 70  FF FE 81 30  00 00 00 5F [.......p...0..._]
00000002- 00 02 00 00  00 00 00 00  3B BF 00 00  C4 17 3B BF [........;.....;.]
00000003- 00 00 C4 17  00 00 00 00  00 00 00 00  80 02 00 00 [................]
00000004- 00 05 00 0A  00 0F 00 14  00 19 00 1E  00 23 00 28 [.............#.(]
00000005- 00 2D 00 32  00 37 00 3C  00 41 00 46  00 00 00 00 [.-.2.7.<.A.F....]
00000006- 00 00 00 00                                        [....            ]

1 Ответ

3 голосов
/ 17 ноября 2011

Поскольку документация перечисляет поле как целое число, но показывает точность, равную 0,001, я предполагаю, что фактическим значением является сохраненное значение, умноженное на 0,001. Целочисленный диапазон будет от -90000 до 90000.

4 байта должны быть объединены в одно целое число. Есть два способа сделать это, с прямым и прямым порядком байтов, и то, что вам нужно, зависит от компьютера, на котором был записан файл. Например, x86-компьютеры с прямым порядком байтов.

int little_endian = buffer[0] | buffer[1]<<8 | buffer[2]<<16 | buffer[3]<<24;
int big_endian    = buffer[0]<<24 | buffer[1]<<16 | buffer[2]<<8 | buffer[3];

&255 используется для удаления расширения знака, которое происходит при преобразовании подписанного символа в целое число со знаком. Вместо этого используйте неподписанный символ, и он вам, вероятно, не понадобится.

Редактировать: Я думаю, что "половинное слово" означает 2 байта, поэтому вам нужно пропустить 20 байтов вместо 10.

...