I am new to C++ and I'm having trouble understanding how to import text from a file. I have a .txt file that I am inputting from and I want to put all of the text from that file into a string. To read the text file I am using the following code:
ifstream textFile("information.txt");
Which is just reading a text file name information. I made a string named text and initialized it to "". My problem is with the following code which I am trying to use to put the text from the .txt file onto the string:
while (textFile >> text)
text += textFile;
I am clearly doing something wrong, although I'm not sure what it is.
while (textFile >> text) won't preserve spaces. If you want to keep the spaces in your string you should use other functions like textFile.get()
Example:
#include <iostream>
#include <string>
#include <fstream>
int main(){
std::ifstream textFile("information.txt");
std::string text,tmp;
while(true){
tmp=textFile.get();
if(textFile.eof()){ break;}
text+=tmp;
}
std::cout<<text;
return(0);}
while (textFile >> text) text += textFile;
You're trying to add the file to a string, which I assume will be a compiler error.
If you want to do it your way, you'll need two strings, e.g.
string text;
string tmp;
while(textFile >> tmp) text += tmp;
Note that this may omit spaces, so you may need to manually re-add them.
Related
This question already has answers here:
Deleting specific line from file
(3 answers)
Closed 4 years ago.
I want to search for a string in a text file and delete the whole line when it's found. I want to write this in C++.
I've tried solutions in C#, and I've tried creating temporary files. Nothing works for me.
Here's my code so far:
void MainForm::WriteToTextFile(){
ifstream stream("text.txt");
string line;
bool found = false;
while (std::getline(stream, line) && !found)
{
if (line.find("Delete_This_Line") != string::npos){ // WILL SEARCH "Delete_This_Line" in file
found = true;
line.replace(line.begin(), line.end(), "\n");
stream.close();
}
I expected that the text file would be modified but nothing has changed.
You don't write anything to the file.
And for text files, you can't simply "replace" text, not unless the replacement is the exact same length as the old text you want replaced.
One common way to solve your problem is to read from the original file, writing to a temporary file. When you find the text you want to be replaced then you write the new text to the temporary file. Once you're done then you close both files, and rename the temporary file as the original file, replacing it with your new modified content.
You modify only a string in the memory, how can you expect that change the content of the read file ?
Note also to continue to try to read into the file while you closed it, you test found too late after the getline(), and is more simple to just add a break
std::getline duplicates the line to another string object inside memory. Modifying that string will not change the contents of the file.
A possible solution is to recreate the file using input and output file streams and avoid copying just the desired line. Here is an untested example:
#include <fstream>
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
bool replace_line(string filename, string key, string new_content)
{
{
ifstream stream(filename);
ofstream ofs(filename + ".out");
string line;
bool found = false;
while (std::getline(stream, line))
{
if (line.find(key) != string::npos){
found = true;
ofs << new_content;
} else {
ofs << line;
}
}
}
remove(file);
rename(file + ".out", filename);
return found;
}
I just wondering cause i have a text file containing STATUS:USERID:PASSWORD in accounts.txt
example it would look like this:
OPEN:bob:askmehere:
OPEN:john:askmethere:
LOCK:rob:robmypurse:
i have a user input in my main as such user can login 3x else status will change from OPEN to LOCK
example after 3 tries of john
before:
OPEN:bob:askmehere:
OPEN:john:askmethere:
LOCK:rob:robmypurse:
after:
OPEN:bob:askmehere:
LOCK:john:askmethere:
LOCK:rob:robmypurse:
what i have done is:
void lockUser(Accounts& in){
// Accounts class consist 3 attributes (string userid, string pass, status)
ofstream oFile;
fstream iFile;
string openFile="accounts.txt";
string status, userid, garbage;
Accounts toupdate;
oFile.open(openFile);
iFile.open(openFile);
while(!iFile.eof()){
getline(iFile, status, ':');
getline(iFile, userid, ':');
getline(iFile, garbage, '\n');
if(userid == in.getUserId()){
toupdate.setUserId(in.getuserId());
toupdate.setPassword(in.getPassword());
toupdate.setStatus("LOCK");
break;
}
//here i should update the account.txt how do i do that?
ofile.open(openFile);
ofile<<toupdate.getStatus()<<":"<<toupdate.getUserId()":"<<toupdate.getPassword()<<":"<<endl;
}
There are two common ways to replace or otherwise modify a file. The first and the "classic" way is to read the file, line by line, check for the line(s) that needs to be modified, and write to a temporary file. When you reach the end of the input file you close it, and rename the temporary file as the input file.
The other common way is when the file is relatively small, or you have a lot of memory, is to read it all into memory, do the modification needed, and then write out the contents of the memory to the file. How to store it in memory can be different, like a vector containing lines from the file, or a vector (or other buffer) containing all characters from the file without separation.
Your implementation is flawed because you open the output file (which is the same as the input file) inside the loop. The first problem with this is that the operating system may not allow you to open a file for writing if you already have it open for reading, and as you don't check for failure from opening the files you will not know about this. Another problem is if the operating system allows it, then your call to open will truncate the existing file, causing you to loose all but the very first line.
Simple pseudo-ish code to explain
std::ifstream input_file("your_file");
std::vector<std::string> lines;
std::string input;
while (std::getline(input_file, input))
lines.push_back(input);
for (auto& line : lines)
{
if (line_needs_to_be_modified(line))
modify_line_as_needed(line);
}
input_file.close();
std::ofstream output_file("your_file");
for (auto const& line : lines)
output_file << line << '\n';
Use ReadLine and find the line you wanna replace, and use replace to replace the thing you wanna replace. For example write:
string Example = "Text to find";
openFile="C:\\accounts.txt"; // the path of the file
ReadFile(openFile, Example);
OR
#include <fstream>
#include <iostream>
#include <string>
int main() {
ifstream openFile;
string ExampleText = BOB;
openFile("accounts.txt");
openFile >> ExampleText;
openFile.replace(Example, "Hello");
}
I want write code to find words in a file and replace words.
I open file, next I find word. I have a problem with replace words.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string contain_of_file,a="car";
string::size_type position;
ifstream NewFile;
NewFile.open("plik1.txt");
while(NewFile.good())
{
getline(NewFile, contain_of_file);
position=contain_of_file.find("Zuzia");
if(position!=string::npos)
{
NewFile<<contain_of_file.replace(position,5, a );
}
}
NewFile.close();
cin.get();
return 0;
}
How can I improve my code?
lose the using namespace std;
don't declare the variables before needed;
I think the English word you were looking for was content -- but I am not an English-native speaker;
getline already returns NewFile.good() in boolean context;
No need to close NewFile explicitly;
I would change the casing on the NewFile variable;
I don't think you can write to an ifstream, and you ought to manage how you are going to replace the contents of the file...
My version would be like:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
int main() {
std::rename("plik1.txt", "plik1.txt~");
std::ifstream old_file("plik1.txt~");
std::ofstream new_file("plik1.txt");
for( std::string contents_of_file; std::getline(old_file, contents_of_file); ) {
std::string::size_type position = contents_of_file.find("Zuzia");
if( position != std::string::npos )
contents_of_file = contents_of_file.replace(position, 5, "car");
new_file << contents_of_file << '\n';
}
return 0;
}
There are at least two issues with your code:
1. Overwriting text in a file.
2. Writing to an ifstream (the i is for input, not output).
The File object
Imagine a file as many little boxes that contain characters. The boxes are glued front to back in an endless line.
You can take letters out of boxes and put into other boxes, but since they are glued, you can't put new boxes between existing boxes.
Replacing Text
You can replace text in a file as long as the replacement text is the same length as the original text. If the text is too long, you overwrite existing text. If the replacement text is shorter, you have residual text in the file. Not good in either method.
To replace (overwrite) the text, open the file as fstream and use the ios::in and ios::out modes.
Input versus Output
The common technique for replacing text is to open the original file for *i*nput and a new file as *o*utput.
Copy the existing data, up to your target text, to the new file.
Copy the replacement text to the new file.
Copy any remaining text to the new file.
Close all files.
okay i'm stumped on how to do this. I managed to get to the line I want to replace but i don't know how to replace it.
say a file called file.txt containts this:
1
2
3
4
5
and I want to replace line 3 so that it says 4 instead of 3. How can I do this?
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
fstream file;
string line;
int main(){
file.open("file.txt");
for(int i=0;i<2;i++){
getline(file,line);
}
getline(file,line);
//how can i replace?
}
Assuming you have opened a file in read/write mode you can switch between reading and writing by seeking, including seeking to the current position. Note, however, that written characters overwrite the existing characters, i.e., the don't insert new characters. For example, this could look like this:
std::string line;
while (std::getline(file, line) && line != end) {
}
file. seekp(-std::ios::off_type(line.size()) - 1, std::ios_base::cur);
file << 'x';
Even if you are at the right location seeking is needed to put the stream into an unbound state. Trying to switch between reading and writing without seeking causes undefined behavior.
The usual approach is to read from one file while writing to another. That way you can replace whatever you want, without having to worry about whether it's the same size as the data it's replacing.
I am able to read my text file. Now i would like to parse the string line by line.
I am using header file and cpp file..
can anyone help me with parsing tutorial.
Where can find a good tutorial for parsing?
You can try http://www.cppreference.com/wiki/ and look at examples of using stringstreams.
I don't see what this has to do with header files, but here's how you parse a stream line by line:
void read_line(std::istream& is)
{
// read the lisn from is, for example: reading whitespace-delimited words:
std::string word;
while(is >> word)
process_word(word);
if( !is.eof() ) // some other error?
throw "Dude, you need better error handling!";
}
void read_file(std::istream& is)
{
for(;;)
{
std::string line;
if( !std::getline(is,line) )
break;
std::istringstream iss(line);
read_line(iss);
}
if( !is.eof() ) // some other error?
throw "Dude, you need better error handling!";
}
Try this:
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream fs("myFile.txt");
string input;
vector<string> sets;
while( getline(fs, input) )
sets.push_back(input);
}
First you need to know if the lines contain fixed length fields or are the fields variable length. Fixed length fields are usually padded with some character such as spaces or zeros. Variable length fields are usually terminated by a character such as a comma or tab.
Variable Length Fields
Use the std::string::find or std::string::find_first to find the ending character; also account for the end of the string as the last field may not contain the terminating character. Use this position to determine the length of the field (ending field position - starting field position). Finally, use std::string::substr to extract the field's content.
Fixed Length Fields
Use the std::string::substr method to extract the text. The starting and ending positions can be calculated using the accumulated lengths of the previous fields, if any, and the size of the current field.
Converting Field Text
The contents of the field may not be a string and will need to be converted to an internal data type. For example, a number. Use std::istringstream to convert the text of the field to an internal data type.