I have a binary file, and let's say at byte 11 to byte 14, representing an integer = 100.
Now I want to replace that integer value = 200 instead of the existing one.
How can I do that using C++?
Thanks
T.
Google is your friend. Searching for "C++ binary files" will give you some useful pages, such as: This useful link
In short, you can do something like this:
int main()
{
int x;
streampos pos;
ifstream infile;
infile.open("silly.dat", ios::binary | ios::in);
infile.seekp(243, ios::beg); // move 243 bytes into the file
infile.read(&x, sizeof(x));
pos = infile.tellg();
cout << "The file pointer is now at location " << pos << endl;
infile.seekp(0,ios::end); // seek to the end of the file
infile.seekp(-10, ios::cur); // back up 10 bytes
infile.close();
}
That works for reading. To open a file for output:
ofstream outfile;
outfile.open("junk.dat", ios::binary | ios::out);
Combining those two and adjusting for your specific needs shouldn't be too hard.
Related
I am trying to read a binary file and I am using the f_in.read((char(*) &tmp, sizeof(tmp)) function. However, each time I call this function it continues reading the file from the position where the previous read function had left off. Is it possible to make the read function start from the beginning of the file each time it is called?
Opening the pixmap.bin file:
int main(){
ifstream f_in;
f_in.open("Pixmap.bin", ios::binary);
if (f_in.fail()) {
cerr<<"Error while opening the file pixmap.bin"<<endl;
f_in.close();
exit(EXIT_FAILURE);
}
The function that I want to use with read starting from the beginning each time:
void Read_Dimensions(ifstream &f_in, int Dimensions[2]) {
uint tmp(0);
for(int i=0; i<2;i++) {
f_in.read((char*) &tmp, sizeof(tmp));
Dimensions[i]=tmp;
}
}
this is relative to the file pointer, try reading this page in the section 'File pointer':
http://www.eecs.umich.edu/courses/eecs380/HANDOUTS/cppBinaryFileIO-2.html
Here the example the give:
int main()
{
int x;
streampos pos;
ifstream infile;
infile.open("silly.dat", ios::binary | ios::in);
infile.seekp(243, ios::beg); // move 243 bytes into the file
infile.read(&x, sizeof(x));
pos = infile.tellg();
cout << "The file pointer is now at location " << pos << endl;
infile.seekp(0,ios::end); // seek to the end of the file
infile.seekp(-10, ios::cur); // back up 10 bytes
infile.close();
}
Wish that helps you.
I have been experiencing a bug for the past day that I have not been able to solve.
I have my first method which is for saving player data:
bool Player::savePlayerData() {
ofstream writeFile(getName() + ".bin", ios::out | ios::binary | ios::trunc);
string writeData;
writeData = formatEntityData() + "<" + formatLocationData() + "<" + formatInventory();
writeFile.write(writeData.c_str(), writeData.length() + 1);
writeFile.close();
return true;
}
Note: Assume that getName(), formatEntityData(), formatLocationData(), and formatInventory() return strings and are functional.
Then I have my load player data method:
bool Player::loadPlayerData(string name) {
ifstream readFile(name + ".bin", ios::in | ios::binary | ios::_Nocreate);
if (readFile.good() && readFile.is_open()) {
string data;
getline(readFile, data, '\0');
vector<string> str = split(data, '<');
parseEntityData(str.at(0));
parseLocationData(str.at(1));
parseInventory(str.at(2));
readFile.close();
return true;
}
readFile.close();
return false;
}
Note: Assume that parseEntityData(), parseLocationData(), parseInventory() have string param, void returns and are functional
Note: Assume that split(string, char) takes in a string with a delim. char and splits into vector correctly
So, here is what I am trying to accomplish (for purposes of simplicity lets assume getName() return "luke"):
•Create luke.bin
•Save string to luke.bin in binary
•Load data from luke.bin in form of a string
When I run the program is not properly reading the player data. Instead it is returning as if nothing is in the file. What am I doing wrong? Any tips, ideas, or thoughts would be greatly appreciated.
Code on brothers!
Typically when you open a binary file in notepad++ it gives seemingly
random characters
It depends on data. The string "Hell world" is the same in binary or text. Numbers will appear as text if they are text formatted.
Example of text format:
fout << 1234 << std::endl; //saved as "1234"
Example of binary data:
int i = 1234;
fout.write(&i, sizeof(i)); //saved as 2 bytes, big-endian or little endian binary
ios::binary stops translation of new line characters.
When writing to file, put the exact size:
writeFile.write(writeData.c_str(), writeData.length());
When reading the file, getline(fin, data, '\0'); will stop when it reaches zero or end of file. You should use EOF instead of zero. Better yet, use this method:
std::ifstream f(filename, ios::binary);
if (f.good())
{
f.seekg(0, ios::end);
size_t filesize = (size_t)f.tellg();
f.seekg(0);
std::string data(filesize, 0);
f.read(&data[0], filesize);
cout << data << endl;
return true;
}
return false;
I'm currently trying to read the contents of a file into a char array.
For instance, I have the following text in a char array. 42 bytes:
{
type: "Backup",
name: "BackupJob"
}
This file is created in windows, and I'm using Visual Studio c++, so there is no OS compatibility issues.
However, executing the following code, at the completion of the for loop, I get Index: 39, with no 13 displayed prior to the 10's.
// Create the file stream and open the file for reading
ifstream fs;
fs.open("task.txt", ifstream::in);
int index = 0;
int ch = fs.get();
while (fs.good()) {
cout << ch << endl;
ch = fs.get();
index++;
}
cout << "----------------------------";
cout << "Index: " << index << endl;
return;
However, when attempting to create a char array the length of the file, reading the file size as per below results in the 3 additional CR chars attributing to the total filesize so that length is equal 42, which is adding screwing up the end of the array with dodgy bytes.
// Create the file stream and open the file for reading
ifstream fs;
fs.seekg(0, std::ios::end);
length = fs.tellg();
fs.seekg(0, std::ios::beg);
// Create the buffer to read the file
char* buffer = new char[length];
fs.read(buffer, length);
buffer[length] = '\0';
// Close the stream
fs.close();
Using a hex viewer, I have confirmed that file does indeed contain the CRLF (13 10) bytes in the file.
There seems to be a disparity with getting the end of the file, and what the get() and read() methods actually return.
Could anyone please help with this?
Cheers,
Justin
You should open your file in binary mode. This will stop read dropping CR.
fs.open("task.txt", ifstream::in|ifstream::binary);
I have got a file that contains data for multiple jpegs (along with some garbage), i need to extract binary from this file, filter out the garbage and create jpegs. I know the starting binary sequence of the jpegs.
char buffer[30];
ifstream fin;
fin.open ("FILENAME.raw", ios::in | ios::binary);
while (!fin.eof())
{
fin.read(buffer,30);
cout<<buffer[2]<<endl;
}
fin.close();
Here i am trying to print the file in binary but, when i run this code, alien characters are printed on the screen.
I think problem here was "cout << buffer[2]" which was converting your binary information to charecters. Try int cast before , also you should use a static "unsigned char array"
because binary data can be unsigned .That will work :
unsigned char buffer[ 30 ];
ifstream fin;
fin.open ("FILENAME.raw", ios::in | ios::binary);
while (!fin.eof())
{
fin.read( (char*)( &buffer[0] ), 30 ) ;
cout << (int)buffer[2] << " ";
}
fin.close();
return 0;
Also if you want to traverse the binary why you are just printing buffer[2].
You should double check the binary contents of the file, as your code seems perfectly fine.
I'm sure I've just missed this in the manual, but how do you determine the size of a file (in bytes) using C++'s istream class from the fstream header?
You can open the file using the ios::ate flag (and ios::binary flag), so the tellg() function will directly give you directly the file size:
ifstream file( "example.txt", ios::binary | ios::ate);
return file.tellg();
You can seek until the end, then compute the difference:
std::streampos fileSize( const char* filePath ){
std::streampos fsize = 0;
std::ifstream file( filePath, std::ios::binary );
fsize = file.tellg();
file.seekg( 0, std::ios::end );
fsize = file.tellg() - fsize;
file.close();
return fsize;
}
Don't use tellg to determine the exact size of the file. The length determined by tellg will be larger than the number of characters can be read from the file.
From stackoverflow question tellg() function give wrong size of file? tellg does not report the size of the file, nor the offset from the beginning in bytes. It reports a token value which can later be used to seek to the same place, and nothing more. (It's not even guaranteed that you can convert the type to an integral type.). For Windows (and most non-Unix systems), in text mode, there is no direct and immediate mapping between what tellg returns and the number of bytes you must read to get to that position.
If it is important to know exactly how many bytes you can read, the only way of reliably doing so is by reading. You should be able to do this with something like:
#include <fstream>
#include <limits>
ifstream file;
file.open(name,std::ios::in|std::ios::binary);
file.ignore( std::numeric_limits<std::streamsize>::max() );
std::streamsize length = file.gcount();
file.clear(); // Since ignore will have set eof.
file.seekg( 0, std::ios_base::beg );
Like this:
long begin, end;
ifstream myfile ("example.txt");
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size: " << (end-begin) << " bytes." << endl;
Since C++17, we have std::filesystem::file_size. This doesn't strictly speaking use istream or fstream but is by far the most concise and correct way to read a file's size in standard C++.
#include <filesystem>
...
auto size = std::filesystem::file_size("example.txt");
I'm a novice, but this is my self taught way of doing it:
ifstream input_file("example.txt", ios::in | ios::binary)
streambuf* buf_ptr = input_file.rdbuf(); //pointer to the stream buffer
input.get(); //extract one char from the stream, to activate the buffer
input.unget(); //put the character back to undo the get()
size_t file_size = buf_ptr->in_avail();
//a value of 0 will be returned if the stream was not activated, per line 3.