Как прочитать шестнадцатеричные значения в целое число с помощью fstream (C ++) - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь прочитать шестнадцатеричную строку с прямым порядком байтов из двоичного файла и поместить это значение в целое число для работы с ним. Когда я пытаюсь читать, вместо числа я получаю символы ascii. Я пробовал бросать и atoi, и, кажется, ничего не работает. Как лучше всего использовать fstream для чтения шестнадцатеричной строки в целое число из файла?

Это по сути моя программа:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(int argc, char* argv[]) {
    fstream input;
    fstream output;
    char cbuffer[4];
    char revbuffer[8];

    input.open(argv[1], fstream::binary | fstream::in);
    output.open("output.txt", ios::out | ios::app);
    input.seekg(16, input.beg);
    input.read(cbuffer, 4);

    cout << sizeof(revbuffer) << endl;
    cout << cbuffer[0] << cbuffer[1] << cbuffer[2] << cbuffer[3] << endl;
}

1 Ответ

0 голосов
/ 19 ноября 2018

Если это целочисленное значение, хранящееся в двоичном формате, я думаю, это либо int32_t, либо uint32_t.Поскольку вы упоминаете, что значение хранится в порядке байтов с прямым порядком байтов, я думаю, вы хотите убедиться, что хост, на котором работает ваша программа, преобразует его (если это необходимо).C ++ 20 имеет std :: endian .Если это вам недоступно, обычно есть макросы для определения порядка байтов во время компиляции, которые вы можете использовать вместо тестов std::endian, которые я использовал.Я предположил, что значение на uint32_t ниже.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <type_traits> // std::endian

// little endian unsigned 32 bit integer to host byte order
inline uint32_t Le32toh(uint32_t le) {
    #if __cplusplus <= 201703L
    // run-time check
    static constexpr uint16_t endian = 1;
    if(*reinterpret_cast<const uint8_t*>(&endian)==1) return le;
    #else
    // compile-time check
    static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big);
    if constexpr (std::endian::native == std::endian::little) return le;
    #endif

    const uint8_t* c=reinterpret_cast<const uint8_t*>(&le);
    return // little-to-big endian conversion
        (static_cast<uint32_t>(c[0])<<24) |
        (static_cast<uint32_t>(c[1])<<16) |
        (static_cast<uint32_t>(c[2])<<8) |
        (static_cast<uint32_t>(c[3]));

    return le;
}


int main(int argc, char* argv[]) {
    std::vector<std::string> args(argv+1, argv+argc);

    std::fstream output("output.txt", std::ios::out | std::ios::app);

    uint32_t cbuffer;

    for(const auto& file : args) {
        std::fstream input(file, std::fstream::binary | std::fstream::in);
        input.seekg(16, input.beg);
        // read directly into the varibles memory
        input.read(reinterpret_cast<char*>(&cbuffer), 4);
        // output the value unconverted
        std::cout << std::hex << cbuffer << "\n";
        // convert if needed
        cbuffer = Le32toh(cbuffer);
        // output the value converted
        std::cout << std::hex << cbuffer << "\n";
    }
}
...