преобразование прочитанной строки из двоичного файла в целое число - PullRequest
0 голосов
/ 07 января 2019

У меня есть бинарный файл. я читаю 16 байт за раз, используя fstream.

Я хочу преобразовать его в целое число. Я попробовал Atoi. но это не сработало. В Python мы можем сделать это путем преобразования в поток байтов с помощью stringobtained.encode ('utf-8'), а затем преобразовать его в int с помощью int (bytestring.hex (), 16). Должны ли мы следовать таким шагам elloborate, как это делается в python, или есть ли способ преобразовать его напрямую?

ifstream file(binfile, ios::in | ios::binary | ios::ate);
if (file.is_open())
{

    size = file.tellg();
    memblock = new char[size];
    file.seekg(0, ios::beg);
    while (!file.eof())
    {
        file.read(memblock, 16);            
        int a = atoi(memblock); // doesnt work 0 always
        cout << a << "\n";
        memset(memblock, 0, sizeof(memblock));
    }
    file.close();

Edit:

Это пример содержимого файла.

53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00
04 00 01 01 00 40 20 20 00 00 05 A3 00 00 00 47
00 00 00 2E 00 00 00 3B 00 00 00 04 00 00 00 01

Мне нужно прочитать его как 16 байт, то есть 32 шестнадцатеричные цифры за раз (т. Е. Одну строку в содержимом образца файла) и преобразовать его в целое число. поэтому при чтении 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 , я должен получить, 110748049513798795666017677735771517696

Но я не мог этого сделать. Я всегда получаю 0 даже после попытки strtoull. Я неправильно читаю файл или чего мне не хватает.

Ответы [ 3 ]

0 голосов
/ 07 января 2019

Это число двоичное, что вы хотите:

    short value ;
    file.read(&value, sizeof (value));            

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

0 голосов
/ 09 января 2019

У вас есть ряд проблем здесь. Во-первых, C ++ не имеет стандартного 128-битного целочисленного типа. Вы можете найти расширение компилятора, см., Например, Есть ли в gcc 128-битное целое число? или Есть ли в C ++ 128-битное целое число? .

Во-вторых, вы пытаетесь декодировать необработанные байты вместо строки символов. atoi остановится на первом нецифровом символе, с которым он столкнется, который в 246 раз из 256 будет самым первым байтом, таким образом, он возвращает ноль. Если вам не повезло, вы прочитаете 16 действительных цифр, и atoi начнет читать неинициализированную память, что приведет к неопределенному поведению.

Вам все равно не нужно atoi, ваша проблема намного проще, чем эта. Вам просто нужно собрать 16 байтов в целое число, что можно сделать с помощью операторов shift и or. Единственное осложнение заключается в том, что read хочет тип char, который, вероятно, будет подписан, а вам нужны неподписанные байты.

ifstream file(binfile, ios::in | ios::binary);
char memblock[16];
while (file.read(memblock, 16))
{
    uint128_t a = 0;
    for (int i = 0; i < 16; ++i)
    {
        a = (a << 8) | (static_cast<unsigned int>(memblock[i]) & 0xff);
    }
    cout << a << "\n";
}
file.close();
0 голосов
/ 07 января 2019

16 шестнадцатеричных цифр означает, что результат может быть длиной 8 байтов. Поэтому atoi не работает. Мы не можем дать основание для atoi, и оно возвращает int, которое обычно составляет 4 байта. То, что мы можем использовать, возможно std::stoull.

Пример:

#include <iostream> 
#include <string>

int main()
{ 
    std::string s = "0000abaafffefffe";
    unsigned long long x = std::stoull(s, nullptr, 16);
    std::cout << x << "\n"; 
} 

188750927691774

...