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().
Related
(My previous questions was closed as a duplicate of Are there binary memory streams in C++ which is ridiculous, since i can't change the implementation of the library I'm using)
I'm using a library (Poco) to create zip files. It takes ostream as an input and writes the data of the zip file into it. Something like:
std::ofstream ofs("file.zip", std::ios::binary);
Compress compress(ofs);
// add data to compress ...
compress.close();
// now file.zip contains added file
This works. But I want to be able to create a zip in memory without creating a file. I tried using stringstream instead of ofstream, i get additionl newline characters in the data in the zip file is corrupted. Is there any other stream i can use?
(If someone still thinks it's a duplicate, I'm gonna need an explanation, since I don't see how this other question is helpful for me)
Use a std::stringstream -- that will create an in-memory string that you can write to as an ostream, and WILL NOT add extra newlines. If you later copy the string to an fstream that was opened in text mode (such as std::cout), then that process may add extra CR characters that are not in the string (nor in the original output).
If you are seeing extra characters corrupting your stream, they are coming from somewhere else -- something besides you compress call/lib is writing to the stream, or something with how you are looking at your stream is doing something.
If you're on linux, how about creating an anonymous file using memfd_create? You can then open /proc/self/fd/<fd> and do your stuff. Some implementations of std::ofstream may even provide a constructor that takes a FILE*, you can check if that's the case on your system.
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.
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.
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().
Consider i have a file, 'emp.txt' whose content is,
EmpNo. Name Phone No. Salary
1 ABC 123 321
2 CBA 456 543
Now i want to change the phone no. 1st Employee alone. When i tried using ios:ate, all the contents of the file got deleted and the new phone no. got inserted. How can i solve this?
If you open a file for just output, the library usually truncates the existing file. To change the existing contents of a file, the easiest way is to open it in 'read/write' mode so that you can seek to the correct position and partially overwrite its contents.
Try something like:
std::fstream filestream( "emp.txt", std::ios_base::in | std::ios_base::out );
or if you're using C streams:
FILE* f = fopen( "emp.txt", "r+" );
Change mode of Stream opening
See all possible Modes here
For your example I think it would better just is to load the whole file, do your change and then write back the whole file. If the file is large then not.
In Windows, MapViewOfFile() works great in the special case where you are just overwriting digits in-place and the tail of the file need not move. If you DO need to rewrite the entire file, there's a Wikipedia entry on "Transactional NTFS" for ultimate peace-of-mind.
Memory-mapped-files in my experience work REALLY well. If your process crashes, typically the very last byte you happened to write will still be flushed to disk correctly, since Windows robustly knows which pages are dirty.
Which SUGGESTS "padding your records" so that even typical Address-changes might be accomplished without moving the tail of the file.