Reading / Writing Strings to Binary Files - c++

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;

Related

How to overwrite a portion of a binary file using C++?

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.

Implementing Huffman Tree

I have a program that produces a huffman tree based on ascii character frequency read in a text input file. The huffman codes are stored in a string array of 256 elements, empty string if character is not read.
I am now trying to implement the huffman tree by writing a function that takes my huffman codes that are stored in a string array and outputting the encoding of input file into an output file.
I soon realized that my current approach defeats the meaning of the assignment. I have tried simply copying the string of codes to output file making my encoded output file bigger than the input file.
I am hoping to get help in changing my current function so that it can output the bits into output file making the output file smaller than input file. I am stuck because I am only reading and writing bytes currently?
My current function(fileName being input file parameter, fileName2 being output file parameter):
void encodeOutput(const string & fileName, const string & fileName2, string code[256]) {
ifstream ifile;//to read file
ifile.open(fileName, ios::binary);
if (!ifile)//to check if file is open or not
{
die("Can't read again"); // function that exits program if can't open
}
ofstream ofile;
ofile.open(fileName2, ios::binary);
if (!ofile) {
die("Can't open encoding output file");
}
int read;
read = ifile.get();//read one char from file and store it in int
while (read != -1) {//run this loop until reached to end of file(-1)
ofile << code[read]; //put huffman code of character into output file
read = ifile.get();//read next character
}
ifile.close();
ofile.close();
}
You can't just use ofile << code[read]; if what you need is writing bits, the smallest unit ofstream understands is a byte.
To overcome that, you can write your bits to some sort of "bit buffer" (a char will do) and write that out once it has 8 bits. I don't know exctly what you code strings look like, but this should do:
char buffer = 0, bit_count = 0;
while (read != -1) {
for (int b = 0; b < code[read].size(); b++) {
buffer << 1;
buffer |= code[read][b] != 0;
bit_count++;
if (bit_count == 8) {
ofile << buffer;
buffer = 0;
bit_count = 0;
}
}
read = ifile.get();
}
if (bit_count != 0)
ofile << (buffer << (8 - bit_count));

c++ - binary files and how can do action on them (print the file)

I write to a file but when I try to read from the file I get an infinite loop
When I work with a regular file I can print this shape but with no binary file. why?
And when I want to do actions on a sample binary file how do I do this if I can not go over the file with a loop?
I would be happy to explain thank you.
main.cpp:
string text;
//getline(cin, text);
text = "3.14159#12#Good Luck!# - 2.718";
char ch2;
fstream outBinary1;// output to text
outBinary1.open("binary1.txt", ios::binary | ios::out);
const char *temp = text.c_str();
outBinary1.write(temp, text.length());
outBinary1.get(ch2);// first char in text
while (!outBinary1.eof()){
cout << ch2 ;
outBinary1.get(ch2);
}
outBinary1.close();
Unfortunately it is hard to understand what you want to establish and have problems with, but I will give it a try.
If you want to read from the file you have to specify ios::inadditionally.
Supposed you want to read from the beginning of the file (after writing), you have to reposition the stream first (according to this). Therefore seekg can be used.
What you want may look like that:
string text;
//getline(cin, text);
text = "3.14159#12#Good Luck!# - 2.718";
char ch2;
// You may want to rename this
fstream outBinary1;// output to text
outBinary1.open("binary1.txt", ios::binary | ios::out | ios::in);
const char *temp = text.c_str();
outBinary1.write(temp, text.length());
outBinary1.seekg(0, outBinary1.beg); // only if you want to read from the beginning
outBinary1.get(ch2);// first char in text
while (!outBinary1.eof()){
cout << ch2 ;
outBinary1.get(ch2);
}
outBinary1.close();
#include <fstream>
#include <iostream>
using namespace std;
void f(){
const string text("3.14159#12#Good Luck!# - 2.718");
fstream outBinary1;
outBinary1.open("binary1.txt", fstream::in | fstream::out | fstream::trunc);
outBinary1.write(text.c_str(), text.length());
outBinary1.seekg (0, outBinary1.beg);
char ch2;
outBinary1.get(ch2);// first char in text
while (outBinary1){
cout << ch2 ;
outBinary1.get(ch2);
}
outBinary1.close();
}
int main(int, char**){
f();
return 0;
}
The two lines to change are
outBinary1.open("binary1.txt", fstream::in | fstream::out | fstream::trunc);
outBinary1.seekg (0, outBinary1.beg);
The first one to force the file to be created and the second one to move the fp back to start. Compiled with g++ and no switches

How to read substitution char with ifstream in C++ ? (SUB in ASCII)

I am having a hard time finding out why I can't read all characters with fstream get function.
My code is the following :
ifstream input_stream(input_filename.c_str(), ios::in);
string input;
if(input_stream)
{
char character;
while(input_stream.get(character))
{
input += character;
}
input_stream.close();
}
else
cerr << "Error" << endl;
By testing a little, I found out that I get a problem when character = 26 (SUB in ASCII) because input_stream.get(26) return false and I get out of my while loop.
I would like to put in my string input all characters from the file including SUB.
I tryed with getline function at first and I got a similar problem.
Could you help me please ?
You need to read a binary stream, not a textual one (since SUB i.e. '0x1a' (that is 26) is a control character in ASCII or UTF8, not a printable one) Use ios::binary at opening time:
ifstream input_stream(input_filename.c_str(), ios::in | ios::binary);
Maybe you would then code
do {
int c= input_stream.get();
if (c==std::char_traits::eof()) break;
input += (char)c;
} while (!input_stream.fail());
Did you consider using std::getline to read an entire line, assuming the input file is still organized in ('\n' terminated) lines?

Reading a file into a binary array in c++

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.