Reputation: 13
I'm trying to read a file and put bytes in a byte buffer, but when i try to read exe or zip file not all bytes are loaded in the buffer. my function:
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;
}
the piece of code that check the buffer:
char* bytes = read_file_bytes(path);
for(int i = 0; i < strlen(bytes); i++)
cout << hex << (unsigned int)(bytes[i]);
Upvotes: 1
Views: 712
Reputation: 595295
strlen()
is designed for text characters, not for binary bytes. It stops counting when it encounters a nul char
(0x00), which binary data is likely to contain.
Your read_file_bytes()
function knows how many bytes it reads in. You need to return that number to the caller, eg:
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);
Note that this approach is very C-ish and error prone. A more C++ approach would look like this instead:
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);
Upvotes: 1