Преобразование двоичных данных, считанных из файла, в указатель char в С++

Я пытаюсь добиться непрерывного преобразования двоичного содержимого, считываемого из файла, в байт. Мой файл samplefile.bin содержит 16 байт и имеет форму двоичного файла . В Hexed.it это будет выглядеть так .

введите здесь описание изображения

В этом случае мне нужно было извлечь эти двоичные значения в шестнадцатеричном формате и сохранить их в char *

Я опубликую свой пример кода здесь.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>

using namespace std;

int main()
{
   uint8_t *ptr;
   long size;
   ifstream file ("samplefile.bin", ios::in|ios::binary|ios::ate);
   size = file.tellg();
   std::vector<uint8_t> memblock(size);
   file.seekg (0, ios::beg);
   file.read(reinterpret_cast<char*>(&memblock[0]), size);
   file.close();
   ptr = new uint8_t[size];
   int z=0;
   for(int i=0; i < memblock.size(); i++)
   {
     std::cout << memblock.at(i) << ' ';
     z=memblock.at(i)&0xff;
     ptr[i] = z;
   }

   cout<<"Output"<<endl;
   for (int i=0;i<memblock.size();i++)
   {
       cout<<ptr[i];
   }
   delete []ptr;

return 0;

}

Я хочу, чтобы ptr передавалось какой-то другой функции. Но вывод этого вывода cout<<ptr[i]<<endl; такой, как показано ниже, что означает, что преобразование не происходит.

╠ ↕ ‼ ¶ ╙ O N ╥ í * : J Z [ \ J

Мне нужно что-то подобное

ptr[0] = 0xCC
ptr[1] = 0x12
...
ptr[15] = 0x4A

Когда я даю вот так cout<<(int)ptr[i]<<endl; , я получаю десятичное значение 0xCC как 204 и то же самое для других отпечатков.

Я уже говорил о C++ чтении двоичного файла и преобразовании в шестнадцатеричный и Преобразование двоичного файла в шестнадцатеричное представление. Я не нашел точного решения, потому что в этих двух ссылках они преобразуют его в строку. Мое намерение не в этом.

Я ссылался на это Как правильно читать данные из бинарного файла в массив символов, который похож на мой. Но это не решило мою проблему.
Я хочу, чтобы это 0xCC было одним байтом, и это должно быть сохранено в ptr[0] и аналогично для других значений

Как обойти эту проблему? Я что-то упустил здесь? Я новичок в C++, помогите решить эту проблему.

Оценивая усилия.


person Vishnu CS    schedule 04.08.2020    source источник


Ответы (2)


Прочитайте файл и скопируйте его данные в вектор char. Вы можете использовать iomanip, например std::hex или std::uppercase, для вывода целочисленного значения в шестнадцатеричный формат.

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

#include <iostream>
#include <iomanip>

std::ifstream file("samplefile.bin", ios::binary);
auto mem = std::vector<char>(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
for (char c : mem)
{
    std::cout << std::uppercase << std::hex << static_cast<int>(c) << endl;
}
person John Park    schedule 04.08.2020
comment
Передайте ссылку (если возможно, const) вектора в функцию. Избегайте передачи больших объектов по значению. - person John Park; 04.08.2020
comment
Ваша вторая строка должна быть изменена, чтобы избежать назначения. Вы можете использовать конструктор диапазона. Вы также можете использовать CTAD и инициализатор по умолчанию. Изменить на --› std::vector mem(std::istreambuf_iterator<char>(file),{}); - person Armin Montigny; 04.08.2020
comment
Спасибо за ответ. Прототип функции уже определен, и мы не можем его изменить. Вот почему я попросил скопировать содержимое в char * - person Vishnu CS; 04.08.2020
comment
Армин, благодаря тебе я лучше учу код. Вишун, вы можете рассмотреть std::copy() от итератора istreambuf до вашего необработанного указателя. - person John Park; 04.08.2020
comment
@Amin Вторая строка не выполняет присваивание в С++ 14 (и даже в С++ 11 с включенной оптимизацией). Использование auto совершенно нормально. - person Konrad Rudolph; 04.08.2020
comment
@JohnPark Можете ли вы отредактировать код, выполнив это std::copy() добавлено - person Vishnu CS; 04.08.2020
comment
@Vishnu std::copy(std::istreambuf_iterator‹char›(ifs), {}, ptr); будет достаточно, где ptr - это выделенный вами указатель. - person John Park; 05.08.2020

В вашем коде есть несколько проблем, в первую очередь тот факт, что вы, кажется, ожидаете, что std::byte8_t будет представлено как шестнадцатеричный дамп по умолчанию при подаче в выходной поток. Это не тот случай. Вам нужно явно указать потоку выполнить необходимое форматирование для вас. И если вы хотите сохранить это представление, вам также потребуется сохранить потоковый результат.

Многие дороги ведут в Рим, и, к сожалению, стандартная библиотека потоков ввода-вывода C++ не делает работу с байтовыми потоками очень эргономичной. Но вот один подход:

#include <cstdint>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vector>

using byte = std::uint8_t;

auto read_bytes(std::istream& is, std::vector<byte>& bytes) -> std::istream& {
    return is.read(& reinterpret_cast<char&>(bytes[0]), bytes.size());
}

auto hexdump(std::vector<byte> const& bytes) -> std::string {
    auto ostr = std::ostringstream();
    ostr << std::uppercase << std::hex << std::setw(2) << std::setfill('0');
    for (auto const c : bytes) {
        ostr << int{c};
    }
    return ostr.str();
}

int main(int argc, char** argv) {
    if (argc != 2) return 1;

    auto fs = std::ifstream(argv[1], std::ios_base::binary | std::ios_base::ate);
    auto const size = fs.tellg();
    fs.seekg(0);
    auto buffer = std::vector<byte>(size);
    if (not read_bytes(fs, buffer)) return 1;

    std::cout << hexdump(buffer) << "\n";
}
person Konrad Rudolph    schedule 04.08.2020