Why does the C++ ofstream write() method modify my raw data? - c++

I have a jpeg image in a char[] buffer in memory, all I need to do is write it out to disk exactly as is. Right now I'm doing this
ofstream ofs;
ofs.open(filename);
ofs.write(buffer, bufferLen);
ofs.close();
but the image doesn't come out right, it looks garbled with random black and white stripes everywhere. After comparing the image with the original in a hex viewer, I found out that the ofstream is modifying the data when it thinks I'm writing a newline character. Anyplace that 0x0A shows up in the original, the ofstream writes as two bytes: 0x0D0A. I have to assume the ofstream is intending to convert from LF only to CRLF, is there a standard way to get it to not do this?

Set the mode to binary when you open the file:
http://www.cplusplus.com/reference/iostream/ofstream/ofstream/

You should set the file mode to binary when you are opening it:
std::ofstream file;
file.open("filename.jpg", std::ios_base::out | std::ios_base::binary);
This way the stream doesn't try to adjust the newlines to your native text format.

Try opening the ofstream as binary.
Something like this should work:
ofstream ofs;
ofs.open(filename, ios::out | ios::binary);
ofs.write(buffer, bufferLen);
ofs.close();

Since you are not opening the file in binary mode, it is set to formatted output by default. In formatted output, your implementation performs conversion of the end-of-line characters as you describe.

I wish I could get my version to write anything at all... no errors, no complaints, nothing wrong when you debug it but it doesn't even try and create the file.
What the hell was wrong with fopen, fwrite and fclose... I never had a problem with them

Related

seekp not seeking to proper location?

I have the following code:
file.open(fileName, ios::in | ios::out | ios::binary);
// many lines later
file.seekp(fooAddr, ios::beg);
printf("foo_addr: %d\n", foo_addr);
file.write((char*)fooStruct, sizeof(FooStruct));
I know that fooAddr is 128 due to the printf.
Yet, for some reason, when I open the target file in my hex editor, the first byte is written at location 80.
Is this possible? Or is there some bug I am overlooking in my program?
I guess, for context, all my file operations are wrapped in a macro that checks if file.goodbit is not 0 (truthy), and if so -- the program immediately exits after printing an error.
Your hex editor is displaying file offsets in hexadecimal format, not in decimal.
Decimal 128 is hex 0x80.

clear data inside text file in c++

I am programming on C++. In my code I create a text file, write data to the file and reading from the file using stream, after I finish the sequence I desire I wish to clear all the data inside the txt file. Can someone tell me the command to clear the data in the txt file. Thank you
If you simply open the file for writing with the truncate-option, you'll delete the content.
std::ofstream ofs;
ofs.open("test.txt", std::ofstream::out | std::ofstream::trunc);
ofs.close();
http://www.cplusplus.com/reference/fstream/ofstream/open/
As far as I am aware, simply opening the file in write mode without append mode will erase the contents of the file.
ofstream file("filename.txt"); // Without append
ofstream file("filename.txt", ios::app); // with append
The first one will place the position bit at the beginning erasing all contents while the second version will place the position bit at the end-of-file bit and write from there.
If you set the trunc flag.
#include<fstream>
using namespace std;
fstream ofs;
int main(){
ofs.open("test.txt", ios::out | ios::trunc);
ofs<<"Your content here";
ofs.close(); //Using microsoft incremental linker version 14
}
I tested this thouroughly for my own needs in a common programming situation I had. Definitely be sure to preform the ".close();" operation. If you don't do this there is no telling whether or not you you trunc or just app to the begging of the file. Depending on the file type you might just append over the file which depending on your needs may not fullfill its purpose. Be sure to call ".close();" explicity on the fstream you are trying to replace.
Deleting the file will also remove the content.
See remove file.
You should create a function which clears all the data of the file and then run it.
void clear()
{
ofstream file("fileout.txt");
file<<"";
}

Mismatch between characters put and read

I'm trying to write a Huffman encoder but I'm getting some compression errors. I identified the problem as mismatches between characters that were put() to the ofstream and the characters read() from the same file.
One specific instance of this problem :
The put() writes ASCII character 10 (Line feed)
The read() reads ASCII character 13 (Carriage return)
I thought read and put read and write raw data ( no character translations ) I'm not sure why this is happening. Can someone help me out?
Here is the ofstream instance for writing the compressed file:
std::ofstream compressedFileStream(getCompressedFileName(),std::ios::binary||std::ios::ate);
and the ifstream instance for reading the same
std::ifstream fileInput(getFileName()+".huf",std::ios::binary);
The code is running on Windows 7 and all streams in the program are opened in binary mode.
Not opening in binary mode due to a typo:
std::ofstream compressedFileStream(getCompressedFileName(),std::ios::binary||std::ios::ate)
should be:
std::ofstream compressedFileStream(getCompressedFileName(),std::ios::binary|std::ios::ate)
// ^
|, not ||.
The symptoms show that you are creating the ofsteam with text mode or you are creating it using a filedesc that is opened in text mode.
You will want to pass ios::binary to it at construction time or it may run in text mode on Windows.
After you added the code, the reason proves to be a typo;
std::ios::binary||std::ios::ate
should be
std::ios::binary|std::ios::ate
On Windows, if you are writing binary data, you need to open the file with the appropriate attributes.
Similarly, if you are reading binary data, you need to open the file with the appropriate attributes.

Replacing data in binary file with fstream and seekp

I'm writing a method to replace a specified string from a binary file and it writes NULLs before the position I set with seekp, then writes the string and closes the stream. I only want to replace some bytes in the file. Before this piece of code I tried out with ofstream with ios::binary and ios::out flags. What's wrong to destroy all data in the file?
Before this piece of code, I open the file with an instance of ifstream to read the same position verifyng the first byte in the string. I only comment this for information.
Thank you all!
The code:
fstream ofs();
ofs.open(nomArchBin,ios::in | ios::out | ios::binary);
if (!ofs.good()) {
cout << "...";
return;
}
ofs.seekp(despEnArchivo,ios::beg);
char* registroChar = registroACadena(reg);
ofs.write(registroChar,cabecera.tamanioReg);
I know this sounds silly, but the only way to open a file for writing
and not to truncate it is to open it for reading as well: if you're
really doing ios::in | ios::out | ios::binary, it should work. (But
since you obviously reentered the code, and didn't copy/paste it, I'm
not sure if this is really what you did.)
Other points you have to pay attention to when trying to seek:
The file must be open in binary mode, and imbued with the "C"
locale. (IMHO, a file opened in binary mode should ignore the locale,
but this isn't what the standard says.)
Both `seekg` and `seekp` have the same effect; using either changes the
position of the other.
The only function which allows seeking to an arbitrary location is
the two argument seek; the one argument form can only be used to seek to
a position previously obtained by a tell.

Writing binary data

I am writing to binary file using fstream and when open the file using binary flag.
I needed to write some text as binary, which a simple write did the trick.
The problem is that I need also to write (as shown in hexadecimal) 0. The value when opened in binary notepad is shown zero, but when tried to write this the value not zero it was value of 30 in hexadecimal.
How you write specific data like this?
You probably just need something like this, improve as you see fit:
ofstream file("output.bin", ios::out | ios::binary);
if (file.good())
{
char buf[1] = {0};
file.write(buf, sizeof(buf));
file.close();
}
Links to more sophisticated solutions and documentation were already posted.
When you open the fstream use the ios::binary flag to specify binary output. More information can be found here.
As for writing 0, when you see 30 in hexidecimal you are writing the character '0', not the binary number 0. To do that with an fstream you can do something like:
my_fstream << 0;
Keep in mind the binary data 0 has no textual representation, so you will not be able to read it in Notepad like you would be able to read the character '0'.
Take a look at this:
http://www.cplusplus.com/forum/general/11272/