I want to open a file (without re-creating it) and write to a specific offset.
This is the current code :
std::ofstream file(conf_file_path, std::ios::app);
file.seekp(offset, std::ios::beg);
const auto& output = file.write(conf_str, conf_str_len);
But it always writes to the end of file (probably due to the app flag)
If I don't use the app flag, it re-creates the file as I open it.
How can I open it without re-create it and be able to write to specific offset ?
it always writes to the end of file (probably due to the app flag)
Yes, this is due to the app flag. Here's what the documentation says:
app - seek to the end of stream before each write
If I don't use the app flag, it re-creates the file as I open it.
If you have out or trunc flags sets in the mode, then it destroys the contents of the file, if it already exists.
How can I open it without re-create it and be able to write to specific offset ?
You may use in|out. This will error out if the file doesn't exist; if it exists, the file will be opened and read from the beginning. If you want the stream to be read from the end, you may set the ate flag additionally.
All of this is clearly documented here; reading the manual really helps.
Related
I am a beginner C++ programmer.
I want to create a binary file, that is uncleared with the previous information that was in it. This is easy to do with RAM, simply by making an array, but how do I do this on a hard drive?
How do I create a uncleared file?
In other words how do I retrieve data that was not "cleared" but just marked "empty".
However, if the OS does not allow it, can I launch linux from USB and run my software?
To keep the content of a file to be written on, you can open a file in append mode with:
[ofstream ofs ("filename", ios::binary | ios::app);][1]
All output operations append at the end of the file. Alternatively, you could also use ios::ate so that the output position starts at the end of the file (but afterwards it's up to you).
With the usual read operations you can retrieve preexisting content, by first positionning yourself using seekp().
Using Windows API's WriteFileGather, I am writing a file to the disk.
I want to append new buffers to the existing file.
What is the way to prevent WriteFileGather from overwriting the existing file?
WriteFileGather will never overwrite the file unless you ask it to - theres no implied overwrite/append option, theres ONLY a 'please write data at file position X option'.
You should open the file handle normally (making sure you've got GENERIC_WRITE access and specifying flags at least flags FILE_FLAG_OVERLAPPED and FILE_FLAG_NO_BUFFERING by using CreateFile
Then you set the position the file writes at by using the Offset and OffsetHigh members of the OVERLAPPED you pass in as the 5th parameter.
This is similar to the way WriteFile works when its running in asynchronous mode - you must specify the position to write at. Its probably easier to learn how to do positional asyncronous writes using WriteFile first then move onto WriteFileGather if you need its additional power.
See here for docs.
EDIT: To answer the comment from Harry, to get the end of file you can either remember how much you've written before (assuming this is a new file you created) or get the current file size from a HANDLE using SetFilePointerEx with distance 0 and method FILE_END which will return to you the end of the file. There are other ways of getting a file size but beware you may get a cached answer (e.g. if iterating over a directory) and so the above is recommended.
Most of the time I want to iteratively add a line to a file, but before I open the file to append to, I'd want to be sure it is an empty file to start with (delete if exists).
It occurs so often that I am guessing there might be something I overlook.
So, what is the most convenient way to remove a file first before appending?
QFile outfile(filename);
if (outfile.open(QFile::Append | QFile::Text))
// An option like `QFile::DELETE_FIRST` or something would be great.
{
...
}
Just don't use QFile::Append - it will open file in append mode, so that all dta is written to the end of the file. You can see all OpenModeFlag's here. Use QIODevice::Truncate instead.
QIODevice::Truncate If possible, the device is truncated before it is opened. All earlier contents of the device are lost.
I am using ofstream to output some text to a file in ios::app mode within a loop. But after some step, I need to clear the content of the file. I know we can do it by either delete the file and open again or to open it again with ios::trunc, but is there any where I can get it done without close and open the file again?
If you have opened it in ios::app mode, there's no way to clear content without opening it again. ofstream can only put text in a file, and as text files are sequential, you can't directly erase data on them.
Note sure if it is possible with io streams, but in general you can truncate an open file by setting its current position to 0 and then setting the EOF marker on the file. In the Win32 API, for instance, you can do that with SetFilePointer() and SetEndOfFile().
I am opening a file with ifstream to check if it exists. Then I close it and open it with ofstream to write to it, and I think setting ios::trunc flag allows me to overwrite it.
However I'd like the ability to keep the file open if it exists, but I used an ifstream to open it so does that mean I can't write to the file till I close and re-open using fstream or ofstream? I didn't use fstream to begin with because that wouldn't tell me if the file was already there or not.
Just open a read-write fstream on the file. You can test if the file previously existed (and was non-empty) by seeking to the end and seeing if you're at a non-zero offset. If so, the file existed, and you can do whatever with it. If not, the file didn't exist or was empty. Assuming you don't need to distinguish between those two cases, you can then proceed as if it did not exist.
For example:
// Error checking omitted for expository purposes
std::fstream f("file.txt", std::ios::in | std::ios::out);
f.seekg(0, std::ios::end)
bool didFileExist = (f.tellg() > 0);
f.seekg(0, std::ios::beg);
// Now use the file in read-write mode. If didFileExist is true, then the
// file previously existed (and has not yet been modified)
The setting ios::trunc erases previous contents of the file.
Try opening the file without this setting; with only the 'write' setting.
this is touching very serios problem - race conditions - what if somebody manages to do something with this file between closing and reopening? unfortunately iostream does not provide any means of resolving that issue - you can use cstdio FILE. If you want to turncate file if exists or create new one if not use fopen(name, "w"). If you want to turncate file if it exists or fail otherwise, then it seems standard library has nothing to offer, and you should go to other libraries or platform specific functions like OpenFile in windows.h