Replacing data in binary file with fstream and seekp - c++

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.

Related

Can't access the file(Internal File Buffer NULL)

I have this strange bug. I have a program which writes text to the file using the fstream, but the file is not being created and therefore no text is appended. When I debug my code, it shows me this:
create_new_file = {_Filebuffer={_Pcvt=0x0000000000000000 <NULL> _Mychar=0 '\0' _Wrotesome=false ...} }.
But whenever I use ofstream everything works.
Here is the code:
std::fstream create_new_file{ fileName.str()};
std::unique_ptr<std::string> changes = std::make_unique<std::string>("");
std::cin >> *changes;
create_new_file << *changes << "\n";
Here is the code which works:
std::ofstream create_new_file{ fileName.str()};
I have seen a similar post on Stack Overflow but the answer did not resolve my issue. I have tried adding the std::ios::trunc to the fstream but that did not help. But whenever I use ofstream everything works just as expected.
The problem is that for bidirectional file streams the trunc flag must always be explicitly specified, i.e., if you want the file content to be discarded then you must write in | out | trunc as the second argument as shown below.
Thus, to solve the problem change std::fstream create_new_file{ fileName.str()}; to :
//-------------------------------------------------------------------------vvvvvvvvvvvvvvv---->explicitly use trunc
std::fstream create_new_file{ "output.txt", ios_base::in | ios_base::out | ios_base::trunc};
Working demo
This file stream buffer open reference is useful. It shows a table with the different modes and what happens when they are used.
When you open a std::fstream the default mode for the constructor is in | out. If we look that up in the table we see that this will fail if the file doesn't exist.
And you never check for failure (which you always should do).
If you only want to write to the file then use std::ofstream as it will open the files in out mode, which creates the file if it doesn't exist.
If you want to only append to the file, still use std::ofstream but use the mode out | app, which will create the file and make sure all output is appended (written to the end).

How could I make my own file extention that works on a raspberry pi from C++?

How could I make my own file extention that works on a raspberry pi from C++?
I would like to make a file extention that keeps information for a custom OS for mobile devices such as phones, and tablets. what would the proper way to code an extention for this? information as in names, DOB, maybe their contacts?, and basically anything on the phone that id need to be stored permanantly. how would I do that?
File extensions don't really mean anything, it's just a part of the the file's name. It helps tell the operating system to what program to run with the given file. So making a file extension is quite simple, you just write your data to a file. Here is a great example of doing it in C++
After you have your binary you can read back just as easily, I'll quote a few lines from this site
A file stream object can be opened in one of two ways. First, you can supply a file name along with an i/o mode parameter to the constructor when declaring an object:
ifstream myFile ("data.bin", ios::in | ios::binary);
Alternatively, after a file stream object has been declared, you can call its open method:
ofstream myFile;
...
myFile.open ("data2.bin", ios::out | ios::binary);
Either approach will work with an ifstream, an ofstream, or an fstream object.
Normally, when manipulating text files, one omits the second parameter (the i/o mode parameter). However, in order to manipulate binary files, you should always specify the i/o mode, including ios::binary as one of the mode flags. For read/write access to a file, use an fstream:
fstream myFile;
myFile.open ("data3.bin", ios::in | ios::out | ios::binary);
To read from an fstream or ifstream object, use the read method. This method takes two parameters:
istream& read(char*, int);
The read member function extracts a given number of bytes from the given stream, placing them into the memory pointed to by the first parameter. It is your responsibility to create and manage the memory where read will place its result, as well as to ensure that it is large enough to hold the number of bytes requested. The bytes that are read and not interpreted, the method does not assume anything about line endings, and the read method does not place a null terminator at the end of the bytes that are read in.
If an error occurs while reading (for example, if you read off the end of a file), the stream is placed in an error state. If that occurs, you can use the gcount method to find out the number of characters that were actually read, and use the clear method to reset the stream to a usable state. Once a stream goes into an error state, all future read operations will fail.
An example:
#include <fstream.h>
...
char buffer[100];
ifstream myFile ("data.bin", ios::in | ios::binary);
myFile.read (buffer, 100);
if (!myFile) {
// An error occurred!
// myFile.gcount() returns the number of bytes read.
// calling myFile.clear() will reset the stream state
// so it is usable again.
}
...
if (!myFile.read (buffer, 100)) {
// Same effect as above
}

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<<"";
}

File handling C++ , opening in ios::app mode, file getting wiped

I am making a programme in turbo C++ which requires input and output to a file as well as retrieving the file data for later use.
fstream file("playlist.txt",ios::in|ios::app);
this is what I use but everytime i close the programme and run it again, all the previous contents get wiped. I thought ios::app "Sets the stream's position indicator to the end of the stream before each output operation".
I tried ios::nocreate also, but to no effect.
You should have fstream::out too:
fstream file("playlist.txt", fstream::in | fstream::out);
Then you can move file pointer to end of file. in and app can't be used together: you need to open for R/W because app implies you won't read.

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...