Считать двоичный файл (exe, zip et c ..) в char *, c ++ - PullRequest
1 голос
/ 22 февраля 2020

Я пытаюсь прочитать файл и поместить байты в байтовый буфер, но когда я пытаюсь прочитать exe или zip-файл, не все байты загружаются в буфер. моя функция:

char* read_file_bytes(const string &name) {
   FILE *img = fopen(name.c_str(), "rb");
   fseek(img, 0, SEEK_END);
   unsigned long filesize = ftell(img);
   char *buffer = (char*)malloc(sizeof(char)*filesize);
   rewind(img);
   fread(buffer, sizeof(char), filesize, img);
   return buffer;
}

кусок кода, который проверяет буфер:

char* bytes = read_file_bytes(path);
for(int i = 0; i < strlen(bytes); i++)
    cout << hex << (unsigned int)(bytes[i]);

1 Ответ

1 голос
/ 22 февраля 2020

strlen() предназначен для текстовых символов, а не для двоичных байтов. Он перестает считать, когда встречает nul char (0x00), который двоичные данные могут содержать.

Ваша функция read_file_bytes() знает, сколько байтов она читает. Вам нужно вернуть это число в вызывающий, например:

typedef unsigned char byte;

byte* read_file_bytes(const std::string &name, unsigned long &filesize)
{
    filesize = 0;

    FILE *img = fopen(name.c_str(), "rb");
    if (!img)
        return NULL;

    if (fseek(img, 0, SEEK_END) != 0)
    {
        fclose(img);
        return NULL;
    }

    long size = ftell(img);
    if (size == -1L)
    {
        fclose(img);
        return NULL;
    }

    byte *buffer = static_cast<byte*>(std::malloc(size));
    if (!buffer)
    {
        fclose(img);
        return NULL;
    }

    rewind(img);
    if (fread(buffer, 1, size, img) < size)
    {
        free(buffer);
        close(img);
        return NULL;
    }

    fclose(img);

    filesize = size;
    return buffer;
}
unsigned long filesize;
byte* bytes = read_file_bytes(path, filesize);

for(unsigned long i = 0; i < filesize; ++i)
    std::cout << std::hex << static_cast<unsigned int>(bytes[i]);

free(bytes);

Обратите внимание, что этот подход очень C -i sh и подвержен ошибкам. Более подход C ++ будет выглядеть следующим образом:

using byte = unsigned char;
// or, use std::byte in C++17 and later...

std::vector<byte> read_file_bytes(const std::string &name)
{
    std::ifstream img;
    img.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    img.open(name.c_str(), std::ifstream::binary | std::ifstream::ate);

    std::ifstream::pos_type size = img.tellg();
    ifs.seekg(0, std::ios::beg);
    // or, use std::filesystem::file_size() instead...

    std::vector<byte> buffer(size);
    img.read(buffer.data(), size);

    return buffer;
}
std::vector<byte> bytes = read_file_bytes(path);
for(byte b : bytes)
    std::cout << std::hex << static_cast<unsigned int>(b);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...