The title explains this fairly well. I have a file that I truncate and write to (as a test to control the initial contents of the file). I then want to do read/write operations with that file. Specifically, I want to write to the end of the file, but read from the beginning.
Procedure:
// (1) Make an initial file (truncated std::ofstream) with some contents
// (2) Close initial file stream
// (3) Re-open file with read and write permissions (std::fstream)
// (4) Set stream read pointer to beginning of file
// (5) Set stream write pointer to the end of file
This is somewhat implied along with the question, but what std::fstream::openmode bitwise parameters should I use to open the file (or is the default std::fstream::in | std::fstream::out good enough)?
fstream doesn't have separate read and write positions you need to seek when changing from read to write.
seekg and seekp both call pubseekpos which for fstream does the same for both input and output: https://en.cppreference.com/w/cpp/io/basic_filebuf/seekpos.
Depending on your use case a separate read and write stream on the same file might work.
Related
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
}
I want to open a file, read the data, and after a calculation, write over the data that I read, but I don't want to close it and re-open it, because this will slow down my program as it does this over and over again and it does slow it down.
Essentially, I have a starting number, then I do some calculations and move on to the next number. Since I don't want to redo all these calculations, I have a file with the starting number in it and a file with the output list. I want to change the starting number so I'm not needlessly redoing calculations. If you need to see some of my code, just say so. Thanks guys/gals/variations thereof.
I'm using c++.
I think it would be better if you have the contents on memory, but anyway you can use seekp to change the pointer to the actual position in file
I believe what you are trying to achieve can be done using fstream the syntax is very similar to this:
std::fstream file;
file.open ("textfile.txt", std::fstream::in | std::fstream::out | std::fstream::app);
Here is a link to a better explanation http://www.cplusplus.com/reference/fstream/fstream/open/
Since I have reached the end of the file, the eof flag will be set. I need to clear that using (ifile is the fstream variable in this example) ifile.clear – then try seeking:
ifile.clear();
ifile.seekg(0, ios::beg);
I've a file on which I require multiple operations. Sometimes I just want to append data at the end of the file, sometimes I just want to read from the file, and sometimes, I want to erase all the data and write form the beginning of the file. And then, I again need to append data at the end of file.
I'm using following code:
ofstream writeToTempFile;
ifstream readFromTempFile;
writeToTempFile.open("tempFile.txt", ios::app | ios::out);
readFromTempFile.open("tempFile.txt", ios::in);
// Reading and Appending data to the file
// Now it is time to erase all the previous data and start writing from the beginning
writeToTempFile.open("tempFile.txt", std::ofstream::trunc); // Here I'm removing the contents.
// Write some data to the file
writeToTempFile.open("tempFile.txt", std::ofstream::app); // Using this, I'm again having my file in append mode
But what I've done doesn't work correctly. Please suggest me some solution in C++. ( Not in C)
The problem with the code is:
I wasn't closing the file before I called the method open again on it.
So, close the file before you re-open it with some different permissions.
When I do
fstream someFile("something.dat", ios::binary|ios::out);
someFile.seekp(someLocation, ios::beg);
someFile.write(someData, 100);
It seems to replace the entire file with those 100 bytes instead of replacing only the appropriate 100 bytes, as if I had specified ios::trunc. Is there a portable way to not have it truncate the file?
Edit: adding ios::in seems to do the trick, by why is this required, and is that standard behavior?
Edit #2: I am not trying to append to the existing file. I need to replace the 100 bytes while leaving the rest unaffected.
You want the append flag, ios::app, if you want to write at the end of the file.
To do it somewhere arbitrarily in the middle of the file, you need to seek to the right place. You CAN do this by opening the file for in and out, but if I were you I'd create a temp file, copy input up to mark, write your new data, copy the rest to EOF, close the files and replace the previous version with the temp file. This is called a "Master File update".
AFAIR ios::out only specifies the file is for output and ios:binary only specifies the files is binary. The default behaviour for a stream is to create a new file and overwrite the old file. If you want to modify an existing file you must open the file with the ios::app flag.
ATM I cannot check my references so be sure to double check, but I felieve that is accurate.
Since the file already exists open it in 'read+write' mode and then do seekp. I think it will work.
fstream someFile("something.dat", ios::binary|ios::out|ios::in);
someFile.seekp(someLocation, ios::beg);
someFile.write(someData, 100);
The ios:in mask tells the file pointer to position at the beginning of the file so it can start reading in from the start. But, you may want to use fseek to set the file pointer at the beginning of the file.
How do I use the ofstream to write text to the end of a file without erasing its content inside?
You can pass the flag ios::app when opening the file:
ofstream ofs("filename", ios::app);
You want to append to the file. Use ios::app as the file mode when creating the ofstream.
Appending will automatically seek to the end of the file.
Use ios::app as the file mode.
The seekp() function allows you to arbitrarily set the position of the file pointer, for open files.
As people have mentioned above, opening the file in the following manner will do:
ofstream out("path_to_file",ios::app);
It will do the trick, if you want to append data to the file by default.
But, if you want to go to the end of the file, in the middle of the program, with the default mode not being ios::app, you can use the following statement:
out.seekp(0,ios::end)
This will place the put pointer 0 bytes from the end of file. http://www.cplusplus.com/reference/ostream/ostream/seekp
Make sure you use the correct seekp(), as there are 2 overloads of seekp(). The one with 2 parameters is favored in this situation.