Reading binary file into char array in c++ - c++

std::streampos size;
char * memblock;
std::ifstream input ("A.JPG", std::ios::in|std::ios::binary|std::ios::ate);
if (input.is_open())
{
size = input.tellg();
memblock = new char [size];
input.seekg (0, std::ios::beg);
input.read (memblock, size);
input.close();
std::cout << "[INPUT]the entire file content is in memory " << sizeof(memblock) << " \n";
}
delete[] memblock;
I would like to use the ifstream to read A.JPG (28KB) and save it into the array memblock. But why do the size of the memblock is 4 instead of 28403 while the variable size is equal to 28403?
Thank you.

Because memblock is a pointer, so the sizeof operator evaluates to the size of the pointer variable, which is 4 bytes.

Thanks all and finally I used the vector instead.
Because seems it is hard to display the result I want (length of the actual char array)
std::vector <char> memblock(0);
if (input.is_open())
{
size = input.tellg();
//memblock = new char [size];
memblock.resize(size);
input.seekg (0, std::ios::beg);
input.read (&memblock[0], size);
input.close();
//std::cout << "[INPUT]the entire file content is in memory " << ((char *)(&memblock+1) - (char *)memblock) / (sizeof(memblock[0])) << " \n";
std::cout << "[INPUT]the entire file content is in memory " << memblock.size() << " \n";

Related

C++ string to C char array for writing to binary file

I am trying to write and read string to/from binary file, but I can't understand why sizeof(t) returns 4.
//write to file
ofstream f1("example.bin", ios::binary | ios::out);
string s = "Valentin";
char* t = new char[s.length()+1];
strcpy(t, s.c_str());
cout << s.length()+1 << " " << sizeof(t) << endl; // prints 9 4
for(int i = 0; i < sizeof(t); i++)
{
//t[i] += 100;
}
f1.write(t, sizeof(t));
f1.close();
// read from file
ifstream f2("example.bin", ios::binary | ios::in);
while(f2)
{
int8_t x;
f2.read((char*)&x, 1);
//x -= 100;
cout << x; //print Valee
}
cout << endl;
f2.close();
It doesn't matter what size I put in char* array t, code always prints "4" as its size. What must I do to write longer than 4 bytes of data?
Here's how to do the writing code the easy way
//write to file
ofstream f1("example.bin", ios::binary | ios::out);
string s = "Valentin";
f1.write(s.c_str(), s.size() + 1);
f1.close();
EDIT the OP actually wants something like this
#include <algorithm> // for transform
string s = "Valentin";
// copy s to t and add 100 to all bytes in t
string t = s;
transform(t.begin(), t.end(), t.begin(), [](char c) { return c + 100; });
// write to file
ofstream f1("example.bin", ios::binary | ios::out);
f1.write(t.c_str(), t.size() + 1);
f1.close();
sizeof(char*) prints the size used by a pointer to (a) char(s). It's 4 on your platform.
If you need the size of the string, you should use strlen. Or, simply, s.length().
char *t is a pointer, not an array, so sizeof will return the size of a pointer on your machine, which is apparently 4 bytes.
The correct way to determine the length of a C-style string is to include <cstring> and use std::strlen.

Convert binary file to hex notation

I would like to obtain this hex notation for a binary I enter in parameter:
The output I obtain and what I want:
This is the code I written, I don't have the good hex number (for the part after 5A) , what I am doing wrong ? How to convert properly the byte I read to hex ?
Thanks.
int main(int argc, char *argv[])
{
std::string parameter = "The\\Path\\To\My\exe.exe";
ifstream::pos_type size;
char * memblock;
ifstream file(parametre, ios::in | ios::binary | ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char[size];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();
cout << "the complete file content is in memory" << endl;
string str = string(memblock, size);
string hexContent = "";
int maxColumn = 0;
std::stringstream ss;
int column = 0;
for (int i = 0; i < size; ++i)
{
ss << std::hex << (int)str[i];
if (column == 8)
{
ss << '\n';
column = 0;
}
column++;
}
std::string mystr = ss.str();
cout << mystr;
}
return 0;
}
Looks like char is signed on your system and you are the victim of sign extension. For example 0x90 is a negative, so when it's converted into an int, that negativity has to be carried through, resulting in 0xffffff90.
Solution
Read the file into unsigned char, or uint8_t from <cstdint> if it is available, instead of an array of char.
char * memblock;
becomes
uint8_t * memblock;
then
memblock = new char[size];
becomes
memblock = new uint8_t[size];
and don't convert it into a string later.
string str = string(memblock, size);
is pointless, you could just as easily have read from memblock, and undoes the unsigned-ness we've established earlier. Just read out of memblock
Do not forget to
delete[] memblock;
when you are done. That leads to
Better solution
Use a std::vector. It cleans up after itself.
std::vector<uint8_t> memblock(size);
file.seekg(0, ios::beg);
file.read(reinterpret_cast<char*>(memblock.data()), size);
//or file.read(reinterpret_cast<char*>(&memblock[0]), size); if no or data method

How properly to read data from binary file to char array

How can i properly write data from binary file to new char array.
I know that this question was asked several times here, but still i couldn't figure out how to do it properly.
This what i have so far..
struct Computer_Details {
char computer_type[99];
int release_year;
float price;
};
Computer_Details pc_details;
cout << "Enter Computer Type: ";
cin.getline(pc_details.computer_type, 255);
cout << "Enter Computer Release Date: ";
cin >> pc_details.release_year;
cout << "Enter Computer Price: ";
cin >> pc_details.price;
cout << "\n\n";
//Create File
ofstream file;
file.open("PC_Database.data", ios::binary | ios::app);
if (!file) cout << "Couldn't open file\n";
else {
file.write((char*)&pc_details, sizeof(Computer_Details));
file.close();
}
ifstream readFile;
readFile.open("PC_Database.data", ios::binary);
if (!readFile) cout << "Couldn't Open File\n";
else {
readFile.seekg(0, ios::end);
int fileSize = readFile.tellg();
int pcCount = fileSize / sizeof(Computer_Details);
readFile.seekg(0, ios::beg);
Computer_Details *pc_details = new Computer_Details[pcCount];
readFile.read((char*)pc_details, pcCount * sizeof(Computer_Details));
char *buff = new char[299];
for (int i = 0; i < pcCount; i++)
{
//write to buff char
}
readFile.close();
}
Try
std::ifstream input(szFileName, std::ios::binary);
data = std::vector<char>(std::istreambuf_iterator<char>(input),
(std::istreambuf_iterator<char>()));
char* charArray = &data[0];
size_t arraySize = data.size();
data vector's buffer is the needed char array. Its constructor's arguments are two iterators. The first one is the current reading position in ifstream (begin of stream in this case). The second one's constructor is default and it is treated as an end iterator.
Probably problem is size of your structure,
check sizes for structure and compare it to size of this structure:
struct Computer_Details {
char computer_type[100];
int release_year;
float price;
};
Same problem is when you trying to read/write structure which contains bool variable between two other types like int.
Try this :
readFile.read((char*)pc_details->computer_type, sizeof(Computer_Details::computer_type));
readFile.read((char*)pc_details->release_year, sizeof(Computer_Details::release_year));
readFile.read((char*)pc_details->price, sizeof(Computer_Details::price));
edit: look at examples in this comment: https://stackoverflow.com/a/119128/7981164
My guess is that you want to shove pc_details into the buff so you can send it somewhere and reconstruct the data.
If that is the case, you could do this:
for( int i=0; i < pcCount; i++ )
{
memcpy( buff, (char*)pc_details, sizeof(computer_details));
buff += sizeof(computer_details);
pc_details++;
}
However, when doing this you must be mindful of alignment and provide
padding accordingly. And your code should check your array bounds.

How to read a binary files and print 3's on screen?

I want to read a binary file of integer type and print the occurrence of the number of 3's in the file. I somehow wrote a program to open and read a binary file.
Here is the couple of problems I am facing:
If I try to print the file on my terminal, the execution continues
forever and the loop never ends.
I have no idea of how to filter out 3's from it.
Here is my code:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streampos size;
char * memblock;
ifstream file ("threesData.bin", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
cout << "the entire file content is in memory";
for (int i = 0; i < size; i += sizeof(int))
{
cout << *(int*)&memblock[i] << endl;
}
delete[] memblock;
}
else
cout << "Unable to open file";
return 0;
}
Here is a way to implement your requirements:
int main()
{
unsigned int quantity = 0U;
ifstream file ("threesData.bin", ios::in|ios::binary|ios::ate);
uint8_t byte;
while (file >> byte)
{
if (byte == 3U)
{
++ quantity;
}
}
cout << "The quantity of 3s is: " << quantity << endl;
return 0;
}
The first step should always get a simple version working first. Only optimize if necessary.
Allocating memory for a file and reading the entire file is an optimization. For example, your platform may not have enough available memory to read the entire file into memory before processing.

simple c++ binary file reading

I have a binary file created by some fortran code. I want to write a c++ code to read this binary file and then spit it out through std::cout. Here is so far my code:
#include<fstream>
#include<iostream>
using namespace std;
int main(){
ifstream file("tofu.txt", ios::binary | ios::in | ios::ate);
ifstream::pos_type size;
if(file.is_open()){
size = file.tellg();
cout << "size = " << size << '\n';
file.seekg(0);
char bar[500];
file.read((char*) (&bar), size);
file.close();
string foo(bar);
cout << "foo = " << foo << '\n';
}
else cout << "Unable to open file";
return 0;
}
However, when compiled and run, the code gives me nothing:
size = 250
foo =
Could someone tell me where I'm doing wrong in the code? Thanks!
You forgot to terminate your char array, leading to undefined behaviour. Fix it like this:
char bar[500];
assert(size < 500);
file.read((char*) (&bar), size - 1);
bar[size] = '\0';
(Make sure you check that size isn't larger than you have space for, too!)