fread() binary mode not working properly in c++ - c++

I was facing a problem with the fread() function while coding in c++ .
The target is to open a file in binary mode for writing using :
fopen_s(&filename,filelocation,"wb"); , write a string and an int to be precise using fwrite(&buffer,size_of_read,count,filename) and then to read back the data into other variables (note that this may seem foolish to write and then read data from the same file in the same program, but this is just for testing purpose, since the project I am working on is strictly based upon encryption, and this is one of the modules)...
Here's my code :
int x = 1; // this is piece of data to write to the file
FILE *src; // the file variable that I am using
string text = "byebye"; // this happens to be the piece of data
src = fopen("F:\\_log.log", "wb"); // open file in binary write mode
fwrite(&text, 1, 7, src); // that's 7 because of 6 characters plus '\0'
fwrite(&x, 4, 1, src); // 4 bytes for int ---> writing x=1 to file
text.clear(); // for verification purpose
fclose(src);
src = fopen("F:\\_log.log", "rb");
int y = 0; // this is the int that will contain read data
string read; // string that contains read data
fread(&read, 1, 7, src); // read the data and store in read
fread(&y, 4, 1, src); // read the stored int into y
cout << "string is : " << read << "\nNumber is : " << y << endl;
The output of the above program seems to be correct for integers but not for strings...
string is :
Number is : 1
The Number is : 1 statements clears that first y was zero but the data from the file had been successfully read and stored in y which then turned to 1
But, if the integer has been correctly read, then why not the string read
Also, there seems to be a sync in text and read because if I change the command text.clear(); to text="higuys"; then the output is :
string is : higuys
Number is : 1
How do I solve this ? (completely unable to understand what in the world is being processed in that code...)
Additional information (though it may not do much good) :
OS : Windows 10
IDE : codeblocks (tried with visual studio too)
Compiler : GNU GCC
Debugger : GDB
I have tried to check for any errors using perror(); and tricks like cout<<fread(&read,1,7,src)<<endl; to check the number of bytes read, but everything was OK. Please help me with this one.....
EDIT :
OK, I have tried using array of char instead of string and it worked !!
But still, one thing is not clear and that is : why are the two strings text and read in sync ?

You need to change
string read;
to
char read[7];
string is a class and not a buffer, so you cannot fread giving the address of a string object.
If the program is not only for a fixed 7 bytes string and not only C (you tagged the question as C++) then you should consider using ifstream/ofstream and string and write/read using operators << and >>.

Related

How do I store the char of a byte in a binary file at a specific index in C++

I am doing a school project where I need to store the byte at a certain index, edit it, and then execute a program, after I am done executing the program , I will have to restore the byte to ensure that the executable does not break.
Here is part of the code that I have tried
unsigned int x; // To convert the hex string into int
stringstream ss;
ss<<hex<<offset;//Offset is the hex string
ss>>x;
file.seekg(x);//To move pointer ( i believe) to the specified offset of the binary file
char bytevalue[1];
file.read(bytevalue,1);
cout << "Final byte value : " << bytevalue[0]<<endl;
The problem I am facing now is that when it is printing bytevalue[0]
it will always be this special character "á" (i cant find the exact letter but it is the same letter but the line goes downwards instead of up).
anyone knows where I could be wrong?

How to get consistent responses from fstream?

When I read in information via fstream, it has ocurred twice in two different programs, that the input given to my program isn't stable, even if a given file doesn't change.
In my most recent program, which is concerned with audio-reading. I'm doing a simple check on the first four letters in the file. These letters are supposed to be RIFF, which they also are - I checked.
So, in order to check the format of a given binary file, I buffer the first four letters and see if they are equal to 'RIFF'.
char buffer[4];
std::ifstream in(fn,std::ios::binary);
in.read(buffer,4);
if(buffer!="RIFF"){//Always wrong atm
std::cout << "INVALID WAV FILE: " << buffer << std::endl;
}
When I first made the program, I recall this working properly. Now though, I get an error via my own cout:
INVALID WAV FILE: RIFFýfK
Does anyone have any idea as to what has gone wrong? Perhaps a way to make fstream more consistent?
You're reading 4 characters but not adding a zero terminator, furthermore your comparison is wrong since you're not comparing strings equality, you should rather do:
char buffer[5];
std::ifstream in(fn, std::ios::binary);
in.read(buffer, 4);
buffer[4] = '\0'; // Add a zero-terminator at the end
if (strcmp(buffer,"RIFF")) { // If buffer isn't {'R','I','F','F','\0'}..
std::cout << "INVALID WAV FILE: " << buffer << std::endl;
}

Binary file not holding data properly

Im currently trying to replace a text based file in my application with a binary one. Im just doing some early tests so the code isn't exactly safe but I'm having problems with the data.
When trying to read out the data it gets about half way before it starts coming back with incorrect results.
Im creating the file in c++ and my client application is c#. I think the problem is in my c++ (which I haven't used very much)
Where the problem is at the moment is I have a vector of a struct that is called DoubleVector3 which consists of 3 doubles
struct DoubleVector3 {
double x, y, z;
DoubleVector3(std::string line);
};
Im currently writing the variables individually to the file
void ObjElement::WriteToFile(std::string file) {
std::ofstream fileStream;
fileStream.open(file); //, ios::out | ios::binary);
// ^^problem was this line. it should be
// fileStream.open(file, std::ios_base::out | std::ios_base::binary);
fileStream << this->name << '\0';
fileStream << this->materialName << '\0';
int size = this->vertices.size();
fileStream.write((char*)&size,sizeof(size));
//i have another int written here
for (int i=0; i<this->vertices.size(); i++) {
fileStream.write((char*)&this->vertices[i].x, 8);
fileStream.write((char*)&this->vertices[i].y, 8);
fileStream.write((char*)&this->vertices[i].z, 8);
}
fileStream.close();
}
When I read the file in c# the first 6 sets of 3 doubles are all correct but then I start getting 0s and minus infinities
Am I doing anything obviously wrong in my WriteToFile code?
I have the file uploaded on mega if anyone needs to look at it
https://mega.co.nz/#!XEpHTSYR!87ihtCfnGXJJNn13iE6GIpeRhlhbabQHFfN88kr_BAk
(im writing the name and material in first then the number of vertices before the actual list of vertices)
Small side question - Should I delimit these doubles or just add them in one after the other?
To store binary data in a stream, you must add std::ios_base::binary to the stream's flags when opening it. Without this, the stream is opened in text mode and line-ending conversions can happen.
On Windows, line-ending conversions mean inserting a byte 0x0D (ASCII for carriage-return) before each 0x0A byte (ASCII for line-feed). Needless to say, this corrupts binary data.

C++ ofstream doesn't write expected numbers into file

Good day,
I'm working on a program, which reads in a binary file (functions for read in are given and work) and then write the modified information back in another binary file. (I'm changing between two formats.) If I use std::cout to give out the numbers to the console right before (or after) I use ofstream to write them in a file. I get out the numbers I anticipate, but if I know input them into ofstream via << or write and then look at the contents of the file. (The conversion from this format to the original one exists and I can use it.) Then I get carbage.
struct Record {
unsigned latch;
float e, x, y, u, v, wt;}
I read in the given file and modify the numbers I read in. (The following is part of the main-function). Header h is defined and there exists a default constructor. phsp.read and copy are given and work. Reclen corresponds to the Record length and ensures, that the header is written right, because it can be different for different inputs.
std::ofstream outs;
outs.open(outfile, std::ios::out | std::ios::trunc);
Header h;
outs.write((char*) &h, reclen - 5);
for (int i=0; i<nMax; ++i){
phsp.read(mp);
copy(mp, ep);
Record rec;
Modify numbers and putting them into rec, which is a struct and given above. Rec should be written into the file
outs<<rec.latch<<rec.e<<rec.x<<rec.y<<rec.u<<rec.v<<rec.wt;
outs.write((char*) &rec.latch, 4);outs.write((char*) &rec.e, 4);
outs.write((char*) &rec.x, 4); outs.write((char*) &rec.y, 4);
outs.write((char*) &rec.u, 4);outs.write((char*) &rec.v, 4);
outs.write((char*) &rec.wt, 4);
outs.write((char*) &rec, reclen);
}
Not one of this writes, what I want into the file, but if I give out the numbers through std::cout and the console. I get the expected numbers.
std::cout<<rec.latch<<' '<<rec.e<<' '<<rec.x<<' '<<rec.y<<' '<<rec.u<<' '<<rec.v<<
' '<<rec.wt<<'\n';
I also checked the outs stream with good() and I also checked that the file is open. I can also write into the file. Also the write and the << output don't give the same output (could be expected). I checked the size of the rec.i and it also corresponds to the size of the structs.
At the end I change the header again, because I have now new information.
outs.seekp(5);
outs.write((char*) &h, reclen - 5);
outs.close();
There I also have the same problem, with false numbers. I noticed that a number of 0 corresponds to 0, but the number 1 is converted to 16777216 for a unsigned int number.
I hope you can help me, I have no idea what is wrong.
You need to decide whether your new file format is supposed to use binary or text representation for data.
Typically when you use ofstream::write() method you're saving your data in binary format, which means it will be represented as an array of bytes with the length equal to the data structure you're writing. Therefore what you will find in the file will not be the number but its binary representation which generally looks like rubbish if seen as text.
You may see the number by using a hex editor, or you can read it back and then interpret it as a type of your choice. For example:
float number;
ifs.read(&number, sizeof(float); // read in the 4 bytes from the file into a float
This is an equivalent of doing:
char* buffer = new char[sizeof(float)];
ifs.read(buffer, sizeof(float)];
float f = *(reinterpret_cast<float*>(buffer));
If you printed out the contents of the buffer before casting it, you'd see the same rubbish you see in your file. Note that reading and writing binary data requires ios::binary flag set.
operator<< is typically used for writing data as text. It is less efficient in terms of space and speed, but has an advantage of being human readable. Writing data as text is as simple as printing it to the screen, e.g.
std::ofstream ofs;
ofs.open("file.txt");
float f = 1.337f;
ofs << "My float: " << f;
std::cout << "My float: " << f;
If you use above code in the same scope, there is no way for the contents in your file to be different from what's shown on your screen.
Finally make sure that your variables are initialized before using them, as in the code you've posted you're not doing it. E.g.
Header h; // <-- this probably contains rubbish until initialized with some values
outs.write((char*) &h, reclen - 5); // <-- writes rubbish

No methods of read a file seem to work, all return nothing - C++

EDIT: Problem solved! Turns out Windows 7 wont let me read/ write to files without explicitly running as administrator. So if i run as admin it works fine, if i dont i get the weird results i explain below.
I've been trying to get a part of a larger program of mine to read a file.
Despite trying multiple methods(istream::getline, std::getline, using the >> operator etc) All of them return with either /0, blank or a random number/what ever i initialised the var with.
My first thought was that the file didn't exist or couldn't be opened, however the state flags .good, .bad and .eof all indicate no problems and the file im trying to read is certainly in the same directory as the debug .exe and contains data.
I'd most like to use istream::getline to read lines into a char array, however reading lines into a string array is possible too.
My current code looks like this:
void startup::load_settings(char filename[]) //master function for opening a file.
{
int i = 0; //count variable
int num = 0; //var containing all the lines we read.
char line[5];
ifstream settings_file (settings.inf);
if (settings_file.is_open());
{
while (settings_file.good())
{
settings_file.getline(line, 5);
cout << line;
}
}
return;
}
As said above, it compiles but just puts /0 into every element of the char array much like all the other methods i've tried.
Thanks for any help.
Firstly your code is not complete, what is settings.inf ?
Secondly most probably your reading everything fine, but the way you are printing is cumbersome
cout << line; where char line[5]; be sure that the last element of the array is \0.
You can do something like this.
line[4] = '\0' or you can manually print the values of each element in array in a loop.
Also you can try printing the character codes in hex for example. Because the values (character codes) in array might be not from the visible character range of ASCII symbols. You can do it like this for example :
cout << hex << (int)line[i]