Delete recently added lines from a text file - c++

I'm writing a program in C++ which writes lines to a text file. In certain circumstances I want it to delete a bunch of recently added lines. The code looks like this:
file << "Some line." << endl; // *
// lots of lines might be written to file here
if (condition2)
// delete all the lines written to file since * including line "Some line."
How do I do it?

Have a look at the seekp and tellp methods of ostream.
I assume your file is some sort of fstream.

This is just a pseudo code, since you too didn't give enough info
if (condition2)
{
/*
1. Read back the file lines till "Some line" marker
in say, std::vector<std::string>
2. Discard other lines after that.
3. Write the contents of std::vector into the file
*/
}

Related

How to clear std::ofstream file buffer?

I am making a console text editor that continuously saves its content to a text file as text is being written to the editor.
FileEditor editor("C://temp/test.txt");
while (true) {
if (_kbhit()) {
editor.keypress(_getche());
system("cls");
std::cout << editor.content();
editor.save();
}
}
In order to directly save the written content to the text file without having to close() and reopen() the file everytime, I flush the ofstream file buffer directly after inserting text into it.
class FileEditor {
private:
std::ofstream _file;
std::string _content;
public:
// ...
void save() {
_file << _content << std::flush;
}
// ...
};
The problem is when I write multiple characters into the console, for example the string abcd, it will write a to the file, then aab, adding ab to the current buffer content, then aababc, and so on.
Therefore, I wish to clear the ofstream file buffer to replace its contents instead of continuously adding new text to the buffer. Is there a method for clearing the file buffer? Is there a better way of doing what I'm trying to achieve?
I tried finding a method for clearing the buffer and I tried searching online for anyone who might've had the same problem as me, but to no avail.
The problem is when I write multiple characters into the console, for example the string abcd, it will write a to the file, then aab, adding ab to the current buffer content, then aababc, and so on.
Your problem has nothing to do with the file buffer. You are not clearing the editor buffer after writing it to the file, so you are writing the same characters to the file over and over.
The user types a, so your editor buffer is a, and you write a to the file.
Then, the user types b, so your editor buffer is now ab, and you write ab to the file.
Then, the user types c, so your editor buffer is now abc, and you write abc to the file.
Then, the user types d, so your editor buffer is now abcd, and you write abcd to the file.
And so on.
You need to write only the new characters that have entered the editor buffer since the last write to the file. For instance, maintain an index into the editor buffer where the last file write left off, and then have the next file write pick up from that index and advance it for the next file write, etc.
Therefore, I wish to clear the ofstream file buffer to replace its contents instead of continuously adding new text to the buffer. Is there a method for clearing the file buffer? Is there a better way of doing what I'm trying to achieve?
The only way to do this with ofstream is to close the re-open the file stream so that the current file content can be truncated. Otherwise, you will have to resort to using platform-specific APIs to truncate the file without closing it first.

C++ std::string append overwrites instead of appending

I have over 80 levels for my game and only one fails the salted sha1 hashing. The reason is salt is being added inside the level file instead of end of it.
The problem occurs only in Ubuntu 16.04 64-bit, works in Windows. It happens at every launch and being inserted to the same position every time.
Level file is 2 lines, first line is the level file and second line is the hash. So I get the first line and append salt to it. But problem is still same with single line file too.
Here is the minimized code:
int main() {
std::ifstream inf("level.txt");
std::string lvl_file;
std::getline(inf, lvl_file);
inf.close();
lvl_file += "MYSECRETSALT"; // lvl_file.append(..) also has same issue
std::cout << lvl_file << std::endl;
}
This code prints the whole level file but MYSECRETSALT gets inside of it not to the end of it. If I print the lvl_file before appending, it prints nicely without missing anything.
// IT SHOULD BE LIKE
...[0,26],[1,61]],"decor_2":[[0,25000]],"decor_3":[[0,25000]],"tiles_3":[[0,25000]]},"ghosts":[],"turrets":[]}MYSECRETSALT
// BUT IT PRINTS LIKE THIS
...[0,26],[1,61]],"decor_2":[[0,25000]],"decorMYSECRETSALT0]],"tiles_3":[[0,25000]]},"ghosts":[],"turrets":[]}
Level file is at bottom of this: https://hastebin.com/ayeduwucid.php
Hardcoding the file into stringstream works normally though.
std::stringstream inf;
inf << R"json(..)json";
That file was written in Windows, and it goes to second line with \n. When I checked it in hex, it actually puts \r\n which leads these problems.

Delete single line in textfile QT

I have a text file which looks like this (Example):
123456789 18-5-2014
985665547 23-12-2016
I've a read/write function in a while(!file.atEnd) construction like this:
while (!file.atEnd())
{
if (date-currentdate<42) {
ui->label->setText(number); //number is the number before the date in the text file
//Here I want the function to delete the current line
}
}
What I want is to delete the line that is just used in the if statement from my text file. By line (as example) I mean 123456789 15-5-2014.But how do I do this?
If the file can be large:
Create a temporary file.
While reading, write into the temp file all the lines except the one that you want to delete.
Delete the original file.
Rename the temporary file as the original file.
If you know that the file is always small, you can optionally do as follows:
Read in memory all the lines, except the one to be deleted.
Rewrite the file using the strings that you now have in memory.

outputting text to a particular line in file using <fstream> header

How can i write some text to a file's particular line using <fstream> header? Is there any function to do that? Thank you.
You can't really do that because the line you write might be longer than then one that exists. So you would clobber a line or have to rewrite the whole file.
If the lines are all exactly the same length, you could do binary writing.
[Edit: the following line was mistakenly added, it's for .NET only]
If you can, use File.ReadAllLines and File.WriteAllLines.
if you want to insert text in line 5 :
1- copy the content of the line 5 to the end of the file on a new file of to a buffer.
2- then write your line. (ater putting cursor in beinnin of line 5)
3- then copy back the lines from the other file.
or, more complicated (not using buffer): (same algorithm as insertion in an array)
you can move all lines atfer the line you want to overwrite to get the eact spae oryour line. then write your line.
for example, you want to write 20 char in line 5.
start by writing 21 char at the end of the file. (if there is a functionthe move charsby 21 characers,i would be easier and perfect).
then put a loop which replace each char with the char in position -21. until un arrive to line 5.
then write your line in line 5.
is that ok ?
The code will look like this:
InputFile.open();
tmpFile.open();
while(InputFile.readline())
{
if (this is where you want the new line)
{
tmpFile.write(newLine);
if(Want to keep the original line)
{
tmpFile.writeLine(oldLine);
}
}
else
{
tmpFile.writeLine(oldLine);
}
}
InputFile.close();
tmpFile.close();
unlink(InputFile);
move tmpFile to InputFile.

std::getline and eol vs eof

I've got a program that is tailing a growing file.
I'm trying to avoid grabbing a partial line from the file (e.g. reading before the line is completely written by the other process.) I know it's happening in my code, so I'm trying to catch it specifically.
Is there a sane way to do this?
Here's what I'm trying:
if (getline (stream, logbuffer))
{
if (stream.eof())
{
cout << "Partial line found!" << endl;
return false;
}
return true;
}
return false;
However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code. std::getline strips off newlines, so I can't check the buffer for a trailing newline. My log message (above) is NEVER tripping.
Is there some other way of trying to check what I want to detect? Is there a way to know if the last line I read hit EOF without finding a EOL character?
Thanks.
This will never be true:
if (getline (stream, logbuffer))
{
if (stream.eof())
{
/// will never get here
If getline() worked, the stream cannot be in an eof state. The eof() and related state tests only work on the results of a previous read operation such as getline()- they do not predict what the next read will do.
As far as I know, there is no way of doing what you want. However, if the other process writes a line at a time, the problems you say you are experiencing should be very rare (non -existent in my experience), depending to some extent on the OS you are are using. I suspect the problem lies elsewhere, probably in your code. Tailing a file is a very common thing to do, and one does not normally need to resort to special code to do it.
However, should you find you do need to read partial lines, the basic algorithm is as follows:
forever do
wait for file change
read all possible input using read or readsome (not getline)
chop input into lines and possible partial line
process as required
end
An istream object such as std::cin has a get function that stops reading when it gets to a newline without extracting it from the stream. You could then peek() or get() it to see if indeed it is a newline. The catch is that you have to know the maximum length of a line coming from the other application. Example (untested) code follows below:
char buf[81]; // assumes an 80-char line length + null char
memset(buf, 0, 81);
if (cin.get(buf, 81))
{
if (cin.peek() == EOF) // You ran out of data before hitting end of line
{
cout << "Partial line found!\n";
}
}
I have to take issue with one statement you made here:
However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code.
It seems like from what you said it would be extremely easy to replicate your problem, if it is what you said. You can easily create a text file in some text editor - just make sure that the last like ends in an EOF instead of going on to a new line. Then point your program at that file and see what results.
Even if the other program isn't done writing the file, in the file that's where the line ends, so there's no way to tell the difference other than waiting to see if the other program writes something new.
edit: If you just want to tell if the line ends in a newline or not, you could write your own getline function that reads until it hits a newline but doesn't strip it.