I am working on ubuntu. I have a file called test.txt. I would like to replace the second line with another line. How can I do that? I don't want to create a new file and delete the first one.
I would like to specify that the lenght of the new line is the same with the length of the ond one
Try something like:
#include <fstream>
#include <string>
int main() {
const int lineToReplace = 14;
std::fstream file("myfile.txt", std::ios::in | std::ios::out);
char line[255];
for (int i=0; i<lineToReplace-1; ++i)
file.getline(line, 255); // This already skips the newline
file.tellg();
file << "Your contents here" << std::endl;
file.close();
return 0;
}
Note that line can hold up to 254 bytes (plus the null terminator), so if your line takes more than that, adjust accordingly.
If the file is small enough you can read it into memory, do whatever modifications you want on the in-memory copy, and the write if back out.
Edit Code as requested:
// A vector to store all lines
std::vector<std::string> lines;
// The input file
std::ifstream is("test.txt")
// Get all lines into the vector
std::string line;
while (std::getline(is, line))
lines.push_back(line);
// Close the input file
is.close();
// All of the file is now in memory, each line a single entry in the vector
// "lines". The items in the vector can now be modified as you please.
// Replace the second line with something else
lines[1] = "Something else";
// Open output file
std::ofstream os("test.txt");
// Write all lines to the file
for(const auto& l : lines)
os << l << '\n';
// All done, close output file
os.close();
This is Python, but it's significantly more readable and terse for this purpose:
f = open('text.txt', 'w+') # open for read/write
g = tempfile.TemporaryFile('w+') # temp file to build replacement data
g.write(next(f)) # add the first line
next(f) # discard the second line
g.write(second_line) # add this one instead
g.writelines(f) # copy the rest of the file
f.seek(0) # go back to the start
g.seek(0) # start of the tempfile
f.writelines(g) # copy the file data over
f.truncate() # drop the rest of the file
You could also use shutil.copyfileobj instead of writelines to do block copying between the files.
Here's how I would do it, without a hard limit on the line length:
#include <fstream>
#include <string>
using namespace std;
int main()
{
fstream file("test.txt",std::ios::in|std::ios::out);
string line;
string line_new="LINE2";
// Skip the first line, file pointer points to beginning of second line now.
getline(file,line);
fstream::pos_type pos=file.tellg();
// Read the second line.
getline(file,line);
if (line.length()==line_new.length()) {
// Go back to start of second line and replace it.
file.seekp(pos);
file << line_new;
}
return 0;
}
Related
I need to write an 8 ball code that has eleven options to display and it needs to pull from a text file. I have it taking lines from the text file but sometimes it takes an empty line with no writing. And I need it to only take a line that has writing.
Here are that options it needs to draw from:
Yes, of course!
Without a doubt, yes.
You can count on it.
For sure!Ask me later.
I'm not sure.
I can't tell you right now.
I'll tell you after my nap.
No way!I don't think so.
Without a doubt, no.
The answer is clearly NO.
string line;
int random = 0;
int numOfLines = 0;
ifstream File("file.txt");
srand(time(0));
random = rand() % 50;
while (getline(File, line))
{
++numOfLines;
if (numOfLines == random)
{
cout << line;
}
}
}
IMHO, you need to either make the text lines all the same length, or use a database (table) of file positions.
Using File Positions
Minimally, create a std::vector<pos_type>.
Next read the lines from the file, recording the file position of the beginning of the string:
std::vector<std::pos_type> text_line_positions;
std::string text;
std::pos_type file_position = 0;
while (std::getline(text_file, text)
{
text_line_positions.push_back(file_position);
// Read the start position of the next line.
file_position = text_file.tellg();
}
To read a line from a file, get the file position from the database, then seek to it.
std::string text_line;
std::pos_type file_position = text_line_positions[5];
text_file.seekg(file_position);
std::getline(text_file, text_line);
The expression, text_line_positions.size() will return the number of text lines in the file.
If File Fits In Memory
If the file fits in memory, you could use std::vector<string>:
std::string text_line;
std::vector<string> database;
while (getline(text_file, text_line))
{
database.push_back(text_line);
}
To print the 10 line from the file:
std::cout << "Line 10 from file: " << database[9] << std::endl;
The above techniques minimize the amount of reading from the file.
I've a multiline file, every line a string.
Example of code.txt:
AAAAA
BB33A
C544W
I have to put some code contained in another file before every string. I'm using this:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
//the file to include before every string
ifstream one("1.txt");
//final output file
ofstream final;
final.open ("final.txt", ofstream::app);
//string file
string line;
ifstream file("code.txt");
while (getline(file,line))
{
final<<one.rdbuf();
final<<line;
}
}
Now, this doesn't work, it works only for the first line of code.txt. What is wrong?
final<<one.rdbuf() works for only the first line because once you stream out the rdbuf the first time, its read pointer is sitting at the end of the 1.txt file data. There is no data left for it to read on subsequent streaming. You would have to reset the one stream back to the beginning of its data on each loop iteration, eg:
while (getline(file,line))
{
final<<one.rdbuf();
final<<line;
one.seekp(0); // <-- add this
}
Otherwise, do as #Check suggests. Read the content of the 1.txt file into memory one time, and then stream that out on each loop iteration, instead of re-reading the file on each iteration.
I would change your final<<one.rdbuf();.
You can use this:
//the file to include before every string
ifstream one("1.txt");
std::string first;
if (one.is_open())
{
// file length and reserve the memory.
one.seekg(0, std::ios::end);
first.reserve(static_cast<unsigned int>(one.tellg()));
one.seekg(0, std::ios::beg);
first.assign((std::istreambuf_iterator<char>(one)),
(std::istreambuf_iterator<char>()));
one.close();
}
//final output file
ofstream final;
final.open ("final.txt", ofstream::app);
//string file
string line;
ifstream file("code.txt");
while (getline(file,line))
{
final<<first;
final<<line;
}
Maybe you want to check this https://stackoverflow.com/a/8737787/3065110
Please look at this minimal working example:
#include <iostream>
#include <fostream>
using namespace std;
int main()
{
fstream file;
file.open("asd.txt", ios_base::out);
file << "this is a sentence!" << endl;
///is it possible at this point to delete the last character, the exclamation mark, from the file asd.txt using the object "file"?
file.close();
return 0;
}
I am writing a sentence to a file asd.txt using a file object file. Is it possible to delete the character ! from asd.txt using file?
You can use a std::ofstream with seekp and write to overwrite the ! with a space ( I tried just deleting the ! or replacing it by '\0' but i can't seem to get that to work )
#include
#include
int main()
{
std::ofstream file;
file.open("asd.txt");
///is it possible at this point to delete the last character, the exclamation mark, from the file asd.txt using the object "file"?
//Yes!
file.write("this is a sentence!", 19); // writes 19 chars to the file
long pos = file.tellp(); // gets the current position of the buffer ( in this case 19)
file.seekp(pos - 1); // subtracts one from the buffer position ( now 18 )
// writes a space that is one char at the current position of the file ( 18, which overwrites the '!' that is in pos 19)
file.write("", 1);
file.close();
return 0;
}
There are many alternatives though, you can always just close the file, reopen the file with std::ios_base::trunc which will clear all the content in the file, Then you can write the string again only up until before the !
file.write("this is a sentence!", 18);
You can also store the string in a std::string and call std::string::pop_back() to remove the last character and then write that into the file after clearing the file contents. Just store the stream into a std::ostringstream and get the string from the ostringstream and then pop_back() the !.
It really depends on your use case, if you want to give more detail I'd be free to help you out a little more.
I want a vector document variable that will look like
document[0] = "I"
document[1] = " "
document[2] = "want"
document[3] = " "
document[4] = "cake"
document[5] = "."
document[6] = "\n"
With the given line in the file "I want cake.\n"
I'm not sure how to go about doing this and everything I found on delimiters will get rid of whitespace or something.
I have an unordered_set of stopwords that I want to remove from a file. The method I have set up will iterate over a vector and remove_if the word is in my stop words.
The goal is to put all the elements in the document vector into a new file without the stop words.
std::vector<string> MakeFileVector(string filename){
//Get the input from the file
std::ifstream input(filename.c_str());
std::vector<string> doc;
string line;
//For each line in the text File
for ( line ; getline( input, line );)
{
//somehow split up each word/space/period/comma/newline char
//and add to the doc vector
//for each word/space/period/comma/newline char
doc.push_back(str)
}
return doc;
}
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
ifstream myfile("textline.txt");
std::vector<std::string> myLines;
std::copy(std::istream_iterator<std::string>(myfile),
std::istream_iterator<std::string>(),
std::back_inserter(myLines));
Here you go!
You can use std::noskipws found here. This will make sure that whitespaces are not skipped when reading from the stream. Alternatively, you can also use std::getline, found here to get the line into your std::string and then do your processing of whitespaces.
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();
}