I am taking contents from one file and transferring them to another. In particular, I am looking for lines that contain the substring "LIBOR/Swap". However, this is irrelevant and I've commented them out. So, this particular code at the moment really takes every line in one .csv file (file) and transfers them to another .csv file (temp).
The issue is that the transferring skips lines. See attached photos to see the lines that it's skipping in the transfer of data.
original file
new file
As you can see, with the first USD LIBOR/Swap line, it skips the 1 Day rate. This happens elsewhere throughout the code.
Any reason as to why? Thanks.
ifstream file;
ofstream temp;
file.open("YC Rate Levels.csv");
temp.open("Temp.csv");
if (file.is_open())
{
string line;
string test = "LIBOR/Swap";
while (getline(file, line))
{
getline(file, line);
//if(line.find(test) != string::npos)
//{
temp << line << endl;
//}
}
temp.close();
file.close();
} else cout << "File did not open.";
std::cin.clear();
std::cin.ignore(32767, '\n');
std::cin.get();
}
You are calling getline(file, line) twice - once inside the while() header and then again inside the body. Remove the second one.
Related
In my program I'm trying to read from some files, store the data into structs, and sort/display the data for an assignment. However, it wasn't quite working right, and after some troubleshooting I noticed that from every read file, the first and third words are skipped for some reason.
The relevant code:
void fillArray(string filename, string arr[])
{
ifstream ifile(filename);
int count = 0;
while (getline(ifile, arr[count++]))
{
getline(ifile, arr[count]);
count++;
}
ifile.close();
}
The relevant files are structured that after every word there's a newline, so getline only gets and stores one word per iteration. Also, it may be relevant as well that the files being read from are entered as arguments via the command prompt.
while (ifile >> arr[count])
{
getline(ifile, arr[count]);
count++;
}
ifile >> arr[count] reads a word & without count being incremented, getline reads the rest of the line & overwrites what was read by ifile >> arr[count]
That may be the cause of some words being skipped - the words read by >> are overwritten.
I'm trying to to read ~36KB and it would take ~20 seconds to finish this loop:
ifstream input_file;
input_file.open("text.txt");
if( !(input_file.is_open()) )
{
cout<<"File not found";
exit(1);
}
std::string line;
stringstream line_stream; //to use << operator to get words from lines
int lineNum=1;
while( getline(input_file,line) ) //Read file line by line until file ends
{
line_stream.clear(); //clear stream
line_stream << line; //read line
while(line_stream >> word) //Read the line word by word until the line ends
{
//insert word into a linked list...
}
lineNum++;
}
input_file.close();
Any help would be appreciated.
stringstream::clear() does not clear all context inside it. It only resets the error and EOF flags, see http://en.cppreference.com/w/cpp/io/basic_ios/clear.
The result is your line_stream accumulates all previous lines and the inner loop will run words over all the accumulated lines again and again.
So the total time you spend is about O(n^2) compared to O(n) of what you expect it to be.
Instead of using the same object across each line, you could define the new line_stream instance inside the while loop to have a brand new and also empty one. Like this:
fstream input_file;
input_file.open("text.txt");
if( !(input_file.is_open()) )
{
cout<<"File not found";
exit(1);
}
std::string line;
int lineNum=1;
while( getline(input_file,line) ) //Read file line by line until file ends
{
stringstream line_stream; // new instance, empty line.
line_stream << line; //read line
while(line_stream >> word) //Read the line word by word until the line ends
{
//insert word into a linked list...
}
lineNum++;
}
input_file.close();
You could attempt the following:
std::ifstream file("text.txt");
std::string str;
while (std::getline(file, str))
{
cout << str; //call function to to retrieve words of str in memory not in file
}
I ran your code in 11ms, but with the mentioned option in 8ms. May be it works for you.
Try compiling with build flag -O2 or -O3.
I was surprised to see that a simple for-loop to read a 1GB file took 4.7 seconds, whereas another higher level language (Dart) did it in 3.x seconds.
After enabling this flag, runtime dropped to 2.1 seconds.
I wrote a code in C++ that writes a .txt file.
Then I want to open the code again and give some information, so I can get a new text depending on what I gave as an input.
For example I want to give the name of a month, and print in another .txt file all the lines that came after the word "November".
I found some solutions, but none of them worked for me!
One solution that I found on stack overflow is the following:
void Keyword(ifstream & stream, string token) {
string line;
while (getline(stream, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
}
}
cout << token << " not found" << endl;
}
I can't print the next lines with the code above.
Any suggestion would be helpful!
Thanks!
If you want to perform operations on files such as 'Read' and/or 'Write',you might want to search on the net(or if you have a C++ book) on topics such as "File I/O operations using C++". Anyways moving on, C++ has 2 basic classes to handle files which are ifstream and ofstream. And to use them you have to include ethier the header fstream(i.e #include<fstream>) or include them separately as #include<ifstream> and #include<ofstream>. ifstream is basically used for all input operations such as reading files etc. Similarly ofstream is used for all output operations such as writing data to files.
You can open a file and write data to it by doing the following,
ofstream myFile("filename");// Create an instance of ofstream and open file for writing data
and to write data to the file use the << operator like below,
myFile<<data;
Similarly, You can open a file and read data as follows,
ifstream myFile("filename");//Create an instance of ifstream and open file to read data
and to read data from the file use the >> operator as shown below,
myFile>>data;
You can also open a file using the method void open(const char *filename, ios::openmode mode); as shown below,
//Writing only
ofstream outFile;
outFile.open("filename.txt",ios::out);
//Reading only
ifstream inFile;
inFile.open("filename.txt",ios::in);
//For reading and writing
fstream file;
file.open("filename.txt",ios::in|ios::out);
//For closing File
outFile.close();
//or
inFile.close();
//or
file.close();
Note the open() method takes various flags such as ios::in for reading mode, ios::out for writing mode, ios::app for adding data to the end etc.
All of these can also combined by using the bit OR operator | as shown below,
outFile.open("filename.txt",ios::out|ios::app);
There is a lot more in IO. I just covered the things required to start.
Here is the solution to your problem. Try to understand it.
#include<iostream>
#include<fstream>
#include<cstring>
using namespace std;
int main()
{
ofstream outFile;
ifstream inFile;
char fileName[10],data[50];
int noLines;
cout<<"Enter Month:"<<endl;
cin>>fileName;
cout<<"Enter Number of lines you want to enter:"<<endl;
cin>>noLines;
outFile.open(fileName,ios::out);
cout<<fileName<<"(Enter Data):";
for(int i=0;i<=noLines;i++)
{
cin.getline(data,50);
outFile<<data<<endl;
}
outFile.close();
cout<<"Openening "<<fileName<<" :"<<endl;
inFile.open(fileName,ios::in);
for(int i=0 ;i<=noLines ;i++)
{
inFile.getline(data,50);
cout<<data<<endl;
}
inFile.close();
return 0;
}
OP has found most of the solution already:
string line;
while (getline(stream, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
}
}
cout << token << " not found" << endl;
But this only prints the lines with the keyword. And always prints the "not found" message. Ooops.
Instead I pitch:
string line;
bool found = false;
while (!found && getline(stream, line))
{ // search for keyword
if (line.find(token) != string::npos)
{
found = true; // found keyword. Stop looking
}
}
if (found)
{ // print out all remaining lines in the file
while (getline(stream, line))
{
cout << line << endl;
}
}
else
{
cout << token << " not found" << endl;
}
The above splits the finding of the token and the printing of the remaining file into two stages for readability. It can be compressed into one loop, but two things make this a sucker bet:
this program will be IO bound. It will spend the vast majority of its time reading the file, so little tweaks that do not address getting the file into memory are wasted time.
combining the loops would require the addition of logic to the loop that would, over along run, dwarf the minuscule cost of switching loops.
Try this:
http://www.cplusplus.com/doc/tutorial/files/
and this:
http://www.cplusplus.com/forum/beginner/14975/
It's about reading and writing files in c++ and about searching in files.
I'm trying to write a simple program that will print the contents of a text file one line at a time. However, whenever I run the program i just get a blank screen. I'm certain the file I am trying to read contains text over several lines. Any help as to why this isn't working would be super helpfull.
bool show() {
string line;
ifstream myfile;
myfile.open("tasks.txt", ios::app);
while (!myfile.eof()) {
getline (myfile, line);
cout << line << endl;
}
myfile.close();
return true;
}
The problem might be that you are using ios::app with ifstream (input stream), which makes no sense.
According to this,
ios::app: All output operations are performed at the end of the file, appending the content to the current content of the file. This flag can only be used in streams open for output-only operations.
Try this:
std::string line;
ifstream myfile ("tasks.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
std::cout << line << std::endl;
}
myfile.close();
}
Did you check return value of myfile.isopen()? Perhaps the file isn't there or you don't have read permission.
Oh yes, I missed that - the append flag. Should be ios::in
This code always prints the last line of the file. I expected it to print all the text, one line at a time, from the file. Any idea why it doesn't work?
string filename;
cout << "File to read: ";
cin >> filename;
ifstream afile;
afile.open(filename.c_str());
string line;
while(!afile.eof()) {
getline(afile, line);
cout << line;
}
afile.close();
Trying it this way does the same thing:
for (string line; getline(afile, line);) {
cout << line;
}
Maybe this is an issue with my terminal? This works...
for (string line; getline(afile, line);) {
cout << line << endl;
}
The problem is that only the last line is printed. Correct?
I suggest that you add std::endl in your while loop. It can make the issue more clear. Sometimes the output can be confusing.
You can also check the line-delimiting character in your input file. '\n' is the default delimiter for getline. If a different character is used, specify it as getline's 3rd parameter.
From cplusplus.com:
If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it.
Since your original code snippet doesn't insert any extra newlines itself, there is nothing making the output to the terminal go to the next line. When the output runs out of horizontal space what happens next is up to the terminal. I'm not sure what terminal you're using but in your case, it just wraps the cursor back to the first character on that line without a linefeed. On a windows command shell, it just wraps around to the next line.
Also note that:
while(!afile.eof()) {
getline(afile, line);
cout << line;
}
is a common antipattern. As already pointed out, more appropriate would be:
while(getline(afile, line)) {
cout << line << '\n';
}
The file stream only becomes false after you've reached eof and try to read from it.