seekp not seeking to proper location? - c++

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.

Related

Why is this not working? (Trying to convert a text file into a binary file)

#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<algorithm>
#include <sstream>
#include<iomanip>
using namespace std;
const string binaryfile = ".../binaryfile.dat";
void to_binary(const string& filename)
{
ifstream ist(filename);
ofstream ost(binaryfile, ios::binary);
char ch;
while (ist.get(ch))
{
ost.write((char*)&ch, sizeof(char));
}
}
int main()
{
cout << "Enter input file name:\n";
string ifile;
cin >> ifile;
to_binary(ifile);
}
This seems like it should be working to me but it doesn't? I give input a path to some file on my desktop and then call the function but it's just writing the normal text?
The file I'm giving as input contains this:
test file idk what to put here but yeah
Then I run this and binaryfile.dat gets the exact same text just normal text
binaryfile.dat
Does anyone know what I'm doing wrong? I open ost in binary mode, then get the address of each character I extract from ist, get 1 byte from it and write it to the binary file what's making this output normal text to it..?
Edit : Tried this with an int and it worked I got what I expected: This is what I expected
A file that obviously a human can't read why does it work with ints and not chars?
This is the code I used:
int main()
{
int a = 5;
ofstream out("ItemData.dat", ios::binary);
out.write((char*)&a, sizeof(int));
}
What exactly were you expecting to happen?
There is no such thing as a binary file. It's just a file.
A file is a series of bytes. Nothing more, nothing less.
A text file is a file where each byte "means" a character. For example, the byte value 01000001 means the capital letter A. When you open a file in Notepad, Notepad reads the bytes and displays the corresponding letters. If it sees the byte value 01000001 it displays the capital letter A.
Notepad has no idea whether the file "is a text file" or not. It just looks at the bytes and displays the letters. You can open any file in Notepad, such as an EXE file or a JPEG file, and whenever it happens to contain the byte value 01000001 it will display the capital letter A.
Your code reads bytes from a file in text mode and writes them in binary mode. So it makes a copy of the same file... except for the difference between text mode and binary mode.
So what is that difference? Well, the only difference is that text mode tries to "normalize" line endings. Windows has a tradition that the end of a line of text consists of bytes 00001101 and 00001010 in that order. C has a tradition that the end of a line of text is just the byte 00001010. Text mode does that conversion, so that you can read Windows text files in C.
If the file has the byte value 00001010 without a 00001101 before it, most text editors still display it as a line ending, but until Windows 10, Notepad didn't display it as a line ending. Now Notepad does that too. So you won't see the difference in a text editor. You can see the difference in a hex editor program, which directly shows you the bytes in a file (in hexadecimal). I recommend HxD if you are using Windows.
The main reason for opening binary files in binary mode is because if you open a binary file in text mode, the operating system will add or delete 00001101 bytes which will mess up your binary data. Opening the file in binary mode tells it to please not mess up your binary data.

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.

C++: Patching a binary file using fstream

I have a huge file that is already created. I need to write some data at the start of the file while retaining the other contents of the file as such. The following code corrupts the existing file. Can anyone help me with the right method.
ofstream oFile(FileName,ios::out|ios::binary);
oFile.seekp(0);
oFile.write((char*)&i,sizeof(i));
oFile.write((char*)&j,sizeof(i));
oFile.close();
EDIT:
Basically I want to overwrite some bytes of an already existing file at different locations including start. I know the byte address of locations to write. My write will not change the file size.
I need to do something equivalent to the following code that works:
int mode = O_RDWR;
int myFilDes = open (FileName, mode, S_IRUSR | S_IWUSR);
lseek (myFilDes, 0, SEEK_SET);
write (myFilDes, &i, sizeof (i));
write (myFilDes, &j, sizeof (j));
you should perform an:
oFile.seekp(0);
before performing the write. ios::ate implies you're appending to the file.
You also need to use ios::in instead of ios::out. ios::out implies you plan on truncating the file, which may have unintented consequences.
It's not intuitive
You are missing ios::in
Use:
ofstream oFile(FileName,ios::out|ios::in|ios::binary);
If you wanna "insert", you've have to know that C++ see the "file" like a stream of bytes... So if you have got it:
|1|5|10|11|2|3|
And you wanna insert data in the first position( set your position at 0 ), you will have to move the rest of the file...

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/

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

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