C++ write to a specific part of text file without overwriting - c++

I'm writing a simple calendar application which saves the data in a text file. I use the iCalendar-format, so my text file ends "END:VCALENDAR".
When the user adds a new event, the application should write the associated data at the end of the text file without overwriting "END:VCALENDAR", how can I do this? What about deleting an event which is saved in the middle of the text file? Is there a need to write the whole file again using the updated data? Many thanks.

You can't dynamically "expand" the file by writing in the middle of it.
You'll need to, either:
Deserialize the whole calendar to memory, then write it back (best option)
Read into memory everything which lies past the point you want to insert the data, write you data, then write the stored file "tail"

There isn't any way of inserting into the middle of a file; the underlying OS doesn't support it. The usual technique is to copy the file into a temporary file, making whatever modifications you need to along the line, then (and only if there are no errors on the output of the copy—do verify that the output stream has not failed after the close) delete the input file and rename/move the temporary file to the original name.

There is no method supported by the C++ libraries that, unlike append, gives an option to insert at any specific position into a file; be it a text or a binary file.
There are two options for you then:
First is the one you are presuming, that is, read the whole file, update the data and write it back again.
Second is to seek in the file to the last line's first character E as in END:VCALENDAR, write your event and then append "END:VCALENDAR" to it.
And yes, you can find that first character of last line, E right after the last newline character, programmatically.
Sorry, there isn't really any other way around, as far as I know.

Related

Is there a way to control Cursor Point in std::fstream?

I'm reading big datas from .txt file(s) like 1000-5000 persons data. and they saved in a file with alegorithm that i can easily read datas back. but to do it more easy, I'm seeking the way to control File cursor point.
for example in console app you can use VT100 Escape sequences like \033[3A (3 line up) \033[2D (2 Letter Left) \0337 (Save Position)
So is there way to control cursor point like that?
std::fstream can be seen as a linear stream of single bytes. As this, there is no way to use something like "cursor up" which as std::fstream has no knowledge of lines in the file.
What you can do is asking for the current position you are currently reading tellgor writing with tellp.
After keeping such positions, you can go back with seekg or seekp.
If you like you can store current line positions while reading the file and navigate later with this stored position. Alternatively, if you modify the file in a random fashion and the file is not such big, you can read it completely to a data structure of your choice, modify the data internally and write it back later.

can i perform gzseek to update a file compressed using gzwrite (CPP)?

I have a file written using gzwrite. Now i want to edit this file and insert some data in the middle by seeking. Is this possible with gzseek/gzwrite in cpp?
No, it isn't possible. You have to create a new file by successively writing the pieces.
So it is not much different from inserting data in the middle of an uncompressed file, except for one thing: with the uncompressed file, you could leave a hole of the right size (a series of spaces, for example) and later on overwrite that with the data to be inserted, but of course that is not possible with the compressed file because you cannot predict its compressed length.

Can't delete lines from a file, use a stringstream as an alternative?

I've looked at ostream, istream, iostream, and fstream, and I still can't quite figure out how to simply delete lines from an input or output text file just as any clown can do with a text editor.
If I've got a file that reads, for example,
box 1\n
socks\n
box 2\n
pajamas\n
box 3\n
textbooks\n\eof
etc, and I want to totally delete the second box (the 3rd and 4th line) so that the text file reads
box 1\n
socks\n
box 3\n
textbooks\n\eof
I would evidently need to create a temporary file, and place only what I want to keep in that temp file, delete the original file, then rename the temp file with the name of the original file. This is fine and dandy and I understand that it's actually how all programs handle document editing. But it's a tedious pain in the ass to code.
What I'd REALLY love to be able to do is just manipulate what exists without jumping through all these hoops every time I manipulate my text, since I have a huge amount of stuff to sort through and edit.
So this is my hypothesis that I'd like some advice with. Would it be easier to, upon opening the file, to store the entire contents of the file into a string, a vector, a dynamically allocated char array, or perhaps a stringstream, so that I can easily delete parts of it and rearrange it? I could then dump my edited text into a temp text, delete the original, and rename the tempfile with the name of the original file.
Is there any validity to this, or is there a simpler way to do it? I'm tempted to use vectors as my first guess.
[EDIT] Keep in mind that the file I'm dealing with isn't quite so nicely organized to merit the use of structs for easy manipulation of chunks of data. It could be huge paragraphs of prose, or meaningless strings of digits.
If you have many lines and lots of changes, I'm tempted to use a std::list rather than a std::vector.
If you delete or insert often, then the lines must be rearranged. Doing that with a std::vector is more expensive than with a std::list.

Delete record from file C++

I'm working on a simple database console application in C++ for adding, editing and deleting records in a .dat file. I have the addition and modification down, I'm just finding it hard to understand the concept of deletion in this scenario. Below is how I write a record.
Write record
fh.seekp(num*sizeof(customerObj),ios::beg); // Move the write pointer to where rec is
fh.write((char*)&customerObj,sizeof(customerObj)); // Write updated rec
Any ideas how instead of write() I could have something equivalent to delete()... or is it not that simple?
C and C++ don't have functions to delete parts of files. Many operating systems don't either.
Possible options:
If this is the last record, truncate the file. If not, move (=copy) all records after it, overwriting it, then truncate. Alternatively you could move (=copy) the last record to it and then truncate.
Create an extra file and copy to it all records before this and after this record. Then delete the old file and rename the new file.
Mark the record as unused. When writing new records check if you have any unused locations and use them first.
Use a file per record.
Introduce marker of deleted record. So instead of movement of large chunks of file you need write 1 symbol. When you need allocate new record you could iterate over already deleted and just remove marker.
Well, deleting from files is not trivial as you cannot delete a row from a file directly.
One approach is to read the entire file (or in bulks) and write it back without the required line. (quite robust and not efficient for large files).
Maybe if you divide you record file into smaller partitioned files than doing the above will be more efficient.
Another thing you can do is just mark a row in the file as invalid (as done in memory when deleting a pointer) and overwrite it when needed which of course depends on how you write your records but I hope you get what I mean.

How do I truncate a file in Visual C++?

I have the following case. I have a big file say 1 KB. I want to read the first 100 bytes and then delete the 100 bytes read data from the file and then read next 100 bytes. To read 100 bytes is ok, but how do I delete 100 bytes from the file?
This is commonly done as a multiple-step process:
Rename the original file.
Write the data you want into a new file with the original file name.
Delete the old file with the temporary name that contains the data you no longer want.
That way, if something were to go wrong, you could simply restore the original file that you renamed. Moving a file from one place to another is implemented this way, as well.
However, if you don't want to do this, the SetEndOfFile function is another viable option to truncate the contents of a file in-place. From the documentation:
Sets the physical file size for the specified file to the current position of the file pointer.
The physical file size is also referred to as the end of the file. The SetEndOfFile function can be used to truncate or extend a file.
That wouldn't be called truncating; that term refers to removing data from the end, not the beginning. I'm not aware of any operating system where this is possible, other than by copying the contents of the file to a new file, starting at the 100th byte.
Deleting data that has been processed in a file is time consuming and in most cases not necessary.
Deleting data near the top or middle of the file requires writing a new file, which takes time and disk space. Most applications will read and process the entire file then rename the file (with a backup extension). This is useful for debugging purposes. Deleting an entire file is often a faster operation that writing a new file without processed data.
Deletions should only take place when necessary. For files, one can store an offset of where the valid data begins, thus reducing the need to delete data from a file. For secure purposes, overwriting data in the file is often faster then creating a new file without the processed data.
First try writing your program to not delete data in the file. Only delete as necessary, after the program is robust and working correctly. Many people would suggest to only delete files when there is no more space on drive.