Replacing the data in a specific row in the txt file - c++

I'm building a TCP Server application. Two different types of requests come from the client. In the first request type, the client requests a certain number of line information starting from a certain line. For example, the client throws a request like I want to read 3 lines starting at line 5.It's okay so far, I've completed this part, but now let's come to the part where I have difficulty.In the second type of request, the client wants to change the characters in a certain number of lines starting from a certain line.For example change 4 rows starting at row 6.txt file consists of 1s and 0s.txt file is as follows.
1
0
1
0
1
The txt file should be as follows when two line change requests are received, starting from the fourth line.
1
0
1
1
0
I don't use index numbers to identify line numbers, instead I first read the entire file with a loop and push the read data into a vector at each iteration. Thus, when I want to read a particular line, I call the desired index of that vector.
The parts of the code that interest us are shown below.
std::fstream myfile("fc3-4.txt", std::ios_base::in);
int reg;
std::vector<int> registers_vec;
while (myfile >> reg)
{
registers_vec.push_back(reg);
}
As a result of my research, I found to delete a specific data, but this does not work for me because for example, if I write 1 to the value to be deleted, it deletes all the 1s in the txt file.How can I replace a certain number of rows starting from a certain row as I mentioned above.Thanks in advance

First read the complete file into memory. Then close the file.
Make the modifications in memory.
Then, after modifications have been done, write the complete vector to the file.
E.g.:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
int main() {
// Open the file and check, if it could be opened
if (std::ifstream dataStream{ "fc3-4.txt" }; dataStream) {
// Read all vallues in vector data
std::vector data(std::istream_iterator<int>(dataStream), {});
// And close the file
dataStream.close();
// Do any modification. Example flip bits for line 6 to 8
for (size_t line{ 6 }; data.size() > 8 and line < 8; ++line)
data[line] = 1 - data[line];
// Write all file to file
{
if (std::ofstream dataStream{ "fc3-4.txt" }; dataStream) {
// Write all data to file
std::copy(data.begin(), data.end(), std::ostream_iterator<int>(dataStream, "\n"));
}
else std::cerr << "\nError, Cannot open file for writing\n";
}
}
else std::cerr << "\nError, Cannot open file for reading\n";
}

Related

Reading numbers from a chosen line in a file C++

I want to know if I can read numbers from a chosen line in a file in c++.For example if I have .txt file like :
2 3
1 2 3 4
4 5 6 7
There are 3 lines, how can I read only the numbers on line 2 without having to read anything else?
Unless you know the exact file offset of the second line from a previous call to std::istream::tellg, then you will have to read the first line in order to get to the position of the second line. You can use the function std::getline for reading the first line as a std::string, or you can use std::istream::ignore to read and discard the first line, like this:
input.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
If you do happen to know the exact offset of the second line, then you can call std::istream::seekg in order to directly jump to that offset.
Note, howevever, that a file offset does not necessarily correspond to the number of characters that you see when reading the file in text mode. For example, on different platforms, line endings may consist of a different number of characters, which get translated to the single character \n when reading the file in text mode. However, the file offset required by std::istream::seekg is the offset in binary mode. Therefore, you should generally not attempt to calculate such an offset yourself (unless you opened the stream in binary mode, which you should not do for text files). You should only use the function std::istream::tellg for obtaining such an offset.
You can read the file line by line in C++ using
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(){
fstream newfile;
newfile.open("file.txt",ios::in);
if (newfile.is_open()){
string tp;
int i=0;
while(getline(newfile, tp)){
if (i==1) {
cout << tp << endl; // this will only print the second line
}
i+=1;
}
newfile.close();
}
}

Reading a specific line from a .txt file

I have a text file full of names:
smartgem
marshbraid
seamore
stagstriker
meadowbreath
hydrabrow
startrack
wheatrage
caskreaver
seaash
I want to code a random name generator that will copy a specific line from the.txt file and return it.
While reading in from a file you must start from the beginning and continue on. My best advice would be to read in all of the names, store them in a set, and randomly access them that way if you don't have stringent concerns over efficiency.
You cannot pick a random string from the end of the file without first reading up that name in the file.
You may also want to look at fseek() which will allow you to "jump" to a location within the input stream. You could randomly generate an offset and then provide that as an argument to fseek().
http://www.cplusplus.com/reference/cstdio/fseek/
You cannot do that unless you do one of two things:
Generate an index for that file, containing the address of each line, then you can go straight to that address and read it. This index can be stored in many different ways, the easiest one being on a separate file, this way the original file can still be considered a text file, or;
Structure the file so that each line starts at a fixed distance in bytes of each other, so you can just go to the line you want by multiplying (desired index * size). This does not mean the texts on each line need to have the same length, you can pad the end of the line with null-terminators (character '\0'). In this case it is not recommended to work this file as a text file anymore, but a binary file instead.
You can write a separate program that will generate this index or generate the structured file for your main program to use.
All this of course, considering you want the program to run and read the line without having to load the entire file in memory first. If your program will constantly read lines from the file, you should probably just load the entire file into a std::vector<std::string> and then read the lines at will from there.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
string filePath = "test.txt";
vector<std::string> qNames;
ifstream openFile(filePath.data());
if (openFile.is_open())
{
string line;
while (getline(openFile, line))
{
qNames.push_back(line.c_str());
}
openFile.close();
}
if (!qNames.empty())
{
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++)
{
int num = rand();
int linePos = num % qNames.size();
cout << qNames.at(linePos).c_str() << endl;
}
}
return 0;
}

C++ copying parts of a file to a new file

I am trying to create a new file with data from two different existing files. I need to copy the first existing file in it's entirety, which I have done successfully. For the second existing file I need to copy just the last two columns and append it to the first file at the end of each row.
Ex:
Info from first file already copied into my new file:
20424297 1092 CSCI 13500 B 3
20424297 1092 CSCI 13600 A- 3.7
Now I need to copy the last two columns of each line in this file and then append them to the appropriate row in the file above:
17 250 3.00 RNL
17 381 3.00 RLA
i.e. I need "3.00" and "RNL" appended to the end of the first row, "3.0" and "RLA" appended to the end of the second row, etc.
This is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
int main() {
//Creates new file and StudentData.tsv
ofstream myFile;
ifstream studentData;
ifstream hunterCourseData;
//StudentData.tsv is opened and checked to make sure it didn't fail
studentData.open("StudentData.tsv");
if(studentData.fail()){
cout << "Student data file failed to open" << endl;
exit(1);
}
//My new file is opened and checked to make sure it didn't fail
myFile.open("file.txt");
if(myFile.fail()){
cout << "MyFile file failed to open" << endl;
exit(1);
}
//HunterCourse file is opened and checked to make sure if didn't fail
hunterCourseData.open("HunterCourse.tsv");
if(myFile.fail()){
cout << "Hunter data file failed to open" << endl;
exit(1);
}
// Copies data from StudentData.tsv to myFile
char next = '\0';
int n = 1;
while(! studentData.eof()){
myFile << next;
if(next == '\n'){
n++;
myFile << n << ' ';
}
studentData.get(next);
}
return 0;
}
I am going bananas trying to figure this out. I'm sure it's a simple fix but I can't find anything online that works. I've looked into using ostream and a while loop to assign each row into a variable but I can't get that to work.
Another approach that has crossed my mind is just to remove all integers from the second file because I only need the last two columns and neither of those columns include integers.
If you take a look at the seekg method of a file-stream, you'll note the second version allows you to implement the location to set an offset from (such as ios_base::end which sets the offset compared to the end of the file. With this you can effectively read backwards from the end of the a file.
Consider the following
int Pos=0;
while(hunterCourseData.peek()!= '\n')
{
Pos--;
hunterCourseData.seekg(Pos, ios_base::end);
}
//this line will execute when you have found the first newline-character from the end of the file.
Much better code is available at this Very Similar question
Another possibility is simply to find how many lines are in the file beforehand. (less fast, but workable), in this case one would simply loop though the file calling getline and increment a count variable, reset to the start, then repeat until reaching the count - 2. Though I wouldn't use this technique myself.

Go to a specific line in file and read it

Problem description
I have a file containing a set of lines. A
File 1:
"Hello How are you"
"The cat ate the mouse"
Based on the the beginning and ending of the lines given by the user as input. I want to go to each line in the file and Extract it.
For examples if user types 1 , 17 then I have to go to line 1 that has a size of 17 characters. He can give any line number in the file.
I read the following Answer Read from a specific spot in a file C++. But I didn't really understand. Why do the lines have to be the same size? If i have the information concerning the beginning and ending of every line in the file. Why can't I access it directly?
Source code
I tried to use the following code which was inspired by Read Data From Specified Position in File Using Seekg But I couldn't extract the lines why?
#include <fstream>
#include <iostream>
using namespace std::
void getline(int, int, const ifstream & );
int main()
{
//open file1 containing the sentences
ifstream file1("file1.txt");
int beg = 1;
int end = 17;
getline(beg,end, file1);
beg = 2;
end = 20;
getline(beg,end, file1);
return 0;
}
void getline(int beg, int end, const ifstream & file)
{
file.seekg(beg, ios::beg);
int length = end;
char * buffer = new char [length];
file.read (buffer,length);
buffer [length - 1] = '\0';
cout.write (buffer,length);
delete[] buffer;
}
This code appears to be using line numbers as byte offsets. If you seek to offset "1" the file seeks forward 1 byte, not 1 line. If you seek to offset 2, the file seeks forward 2 bytes, not 2 lines.
To seek to a specific line you need to read the file and count the number of line breaks until you get to the line you want. There is code that already does this, for example std::getline(). If you don't already know the exact byte offset of the line you want, you can call std::getline() the number of times equal to the line number you want.
Also remember that the first byte of a file is at offset 0 not offset 1, and that different platforms use different bytes to indicate the end of a line (E.g. on Windows it's "\r\n", on Unix it's "\n"). If you're using a library function to read lines, the line ending should be taken care of for you.

C++ length of file and vectors

Hi I have a file with some text in it. Is there some easy way to get the number of lines in the file without traversing through the file?
I also need to put the lines of the file into a vector. I am new to C++ but I think vector is like ArrayList in java so I wanted to use a vector and insert things into it. So how would I do it?
Thanks.
There is no way of finding the number of lines in a file without reading it. To read all lines:
1) create a std::vector of std::string
3 ) open a file for input
3) read a line as a std::string using getline()
4) if the read failed, stop
5) push the line into the vector
6) goto 3
You would need to traverse the file to detect the number of lines (or at least call a library method that traverse the file).
Here is a sample code for parsing text file, assuming that you pass the file name as an argument, by using the getline method:
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
int main(int argc, char* argv[])
{
std::vector<std::string> lines;
std::string line;
lines.clear();
// open the desired file for reading
std::ifstream infile (argv[1], std::ios_base::in);
// read each file individually (watch out for Windows new lines)
while (getline(infile, line, '\n'))
{
// add line to vector
lines.push_back (line);
}
// do anything you like with the vector. Output the size for example:
std::cout << "Read " << lines.size() << " lines.\n";
return 0;
}
Update: The code could fail for many reasons (e.g. file not found, concurrent modifications to file, permission issues, etc). I'm leaving that as an exercise to the user.
1) No way to find number of lines without reading the file.
2) Take a look at getline function from the C++ Standard Library. Something like:
string line;
fstream file;
vector <string> vec;
...
while (getline(file, line)) vec.push_back(line);
Traversing the file is fundamentally required to determine the number of lines, regardless of whether you do it or some library routine does it. New lines are just another character, and the file must be scanned one character at a time in its entirety to count them.
Since you have to read the lines into a vector anyways, you might as well combine the two steps:
// Read lines from input stream in into vector out
// Return the number of lines read
int getlines(std::vector<std::string>& out, std::istream& in == std::cin) {
out.clear(); // remove any data in vector
std::string buffer;
while (std::getline(in, buffer))
out.push_back(buffer);
// return number of lines read
return out.size();
}