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

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.

Related

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.

Appending string in the middle of a text file

here is my code
#include <string>
#include <iostream>
#include <fstream>
int main(void){
fstream myfile2;
myfile2.open("test2.txt", ios::app);
string checkline;
getline(myfile2, checkline);
int razmer=checkline.length();
string balli="256";
myfile2.seekp(razmer);
myfile2<<balli;
}
test2.txt consists of 2 strings, so it is looks like
Ivanov
Petrov
I want to make from Ivanov -> Ivanov 256. With no touching 2nd string. But my code did not work at all. Thanks in advance.
There's no easy way to edit a text file. The usual solution is to read the whole source file into memory, make your modifications in memory, and then write out all of the file.
In your example where the file seems to be line-based, you could read it line by line and put the lines in a std::vector. Edit the line you want to edit, then loop over the vector and write out the lines.
Note: When writing the file, you open it in write mode, so the file is recreated and looses all old contents.

Deleting a specific line in a txt file using istream/ofstream in c++

Here is the code I'm having a trouble with, I have a .txt file that contains a list of users and their passwords using this format: user;password.
I need to search for a user in the file and then delete the line which contains this user.
void deleteauser()
{
string user;
cout<<"Which user do you wish to delete?";
cin>>user;
string line;
string delimiter=";";
string token,token1;
ifstream infile;
infile.open("users.txt",ios::in);
while (getline(infile,line,'\n'))
{
token = line.substr(0, line.find(delimiter));
token1=line.substr(token.length(), line.find('\n'));
if(token==user)
{
//here i need to delete the line of the user that has been found
}
}
infile.close();
}
Read the input file, line by line, writing to a temporary file. When you find lines you don't want then just don't write them to the temporary file. When done rename the temporary file as the real file.
To edit a file you have 2 options:
Read in every line and write out those you want to keep
Seek to the part of the file you want deleted and replace the text with spaces (or similar)
You have the first half pretty much done - just write out what you read to a temporary file and delete/rename to make it the original.
For the second option, you can write to the input file at that point if you use an iofstream (be aware of buffering issues). The better option is to use seekp or seekg to get to the right point before overwriting the file.

Delete recently added lines from a text file

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
*/
}

Accessing to information in a ".txt" file and go to a determinated row

When accessing a text file, I want to read from a specific line. Let's suppose that my file has 1000 rows and I want to read row 330. Each row has a different number of characters and could possibly be quite long (let's say around 100,000,000 characters per row). I'm thinking fseek() can't be used effectively here.
I was thinking about a loop to track linebreaks, but I don't know how exactly how to implement it, and I don't know if that would be the best solution.
Can you offer any help?
Unless you have some kind of index saying "line M begins at position N" in the file, you have to read characters from the file and count newlines until you find the desired line.
You can easily read lines using std::getline if you want to save the contents of each line, or std::istream::ignore if you want to discard the contents of the lines you read until you find the desired line.
There is no way to know where row 330 starts in an arbitrary text file without scanning the whole file, finding the line breaks, and then counting.
If you only need to do this once, then scan. If you need to do it many times, then you can scan once, and build up a data structure listing where all of the lines start. Now you can figure out where to seek to to read just that line. If you're still just thinking about how to organize data, I would suggest using some other type of data structure for random access. I can't recommend which one without knowing the actual problem that you are trying to solve.
Create an index on the file. You can do this "lazily" but as you read a buffer full you may as well scan it for each character.
If it is a text file on Windows that uses a 2-byte '\n' then the number of characters you read to the point where the newline occurs will not be the offset. So what you should do is a "seek" after each call to getline().
something like:
std::vector< off_t > lineNumbers;
std::string line;
lineNumbers.push_back(0); // first line begins at 0
while( std::getline( ifs, line ) )
{
lineNumbers.push_back(ifs.tellg());
}
last value will tell you where EOF is.
I think you need to scan the file and count the \n occurrences since you find the desired line. If this is a frequent operation, and you are the only one you write the file, you can possibly mantain an index file containing such information side by side with the one containing the data, a sort of "poor-man-index", but can save a lot of time.
Try running fgets in a loop
/* fgets example */
#include <stdio.h>
int main()
{
FILE * pFile;
char mystring [100];
pFile = fopen ("myfile.txt" , "r");
if (pFile == NULL) perror ("Error opening file");
else {
fgets (mystring , 100 , pFile);
puts (mystring);
fclose (pFile);
}
return 0;
}