I was reading data from a file using wifstream
the txt file looks like this:
1,2,3,4,5,6,7
2,3,4,5,6,7,8
...
...
each number is an id I needed for my program and comma is the separator
Here is my code
wifstream inputFile(FILE_PATH);
if(inputFile)
{
wchar_t regex;
int id;
while(inputFile)
{
inputFile>>id;
inputFile.get(regex);
cout << id << ", ";
}
inputFile.close();
}
This code works perfectly fine, until I change the reading scheme in which a single line is read at a time, I wanted to do something similar on the line so I can read data from the line while the buffer of the stream pops the data once it's been read like above. But I can't get it working.
Here is my code
wifstream inputFile(FILE_PATH);
wstring line;
if(inputFile)
{
while(!inputFile.eof())
{
std::getline(inputFile, line);
for(int i=0; i<line.length(); i+=2)
{
int id;
wchar_t regex;
wstringstream(line)>>id; // doesn't work as it keep getting the same number
wstringstream(line).get(regex);
cout << id << ", ";
}
cout << endl;
}
inputFile.close();
}
I think the reason it doesn't work is that I'm not using a stream properly and it keeps reading the id at the very first index and never progress no matter how many times I use >> (probably not the right way to use it anyways), I also tried wifstream, no use either.
How am I supposed to get around with this?
You are recreating the wstringstream each time you use it. Move the creation outside the loop:
wifstream inputFile(FILE_PATH);
wstring line;
if(inputFile)
{
while(!inputFile.eof())
{
std::getline(inputFile, line);
wstringstream istring(line);
for(int i=0; i<line.length(); i+=2)
{
int id;
wchar_t regex;
istring>>id;
istring.get(regex);
cout << id << ", ";
}
cout << endl;
}
inputFile.close();
}
Related
I want to load data from a Text file that has been created in the same program into a vector of strings. But no line of text is getting pushed into the vector here.
Here First I am reading data from some input file and then doing some operations (Removing extra spaces) on it then I save this file as "intermediate.txt". This intermediate.txt is being created and all the operations that I want to do happen successfully. Finally, I want to read this file into a vector<string> code but it doesn't work. I can't store anything in the vector<string> code. Its size is Zero.
#include <bits/stdc++.h>
using namespace std;
int main()
{
string inputFileName;
cout << "Enter the Input File Name: ";
cin >> inputFileName;
ifstream f1(inputFileName);
ofstream f0("intermediate.txt");
string text_line;
while (getline(f1, text_line))
{
string word;
istringstream text_stream(text_line);
while (text_stream >> word)
{
f0 << word << " ";
}
f0 << "\n";
}
f0.close()
ifstream file("intermediate.txt");
vector<string> code;
string line;
while (getline(file, line, '\n'))
{
code.push_back(line);
}
for (auto it : code)
{
cout << it << "\n";
}
}
Here's a mini-code review:
#include <bits/stdc++.h> // Don't do this; doesn't even compile for me
using namespace std; // Don't do this either
int main()
{
string inputFileName;
cout << "Enter the Input File Name: ";
cin >> inputFileName;
ifstream f1(inputFileName); // Bad name
ofstream f0("intermediate.txt"); // Bad name
// You never check that you successfully opened *any* files.
string text_line;
/*
* You don't describe why this is necessary, can a line not be read and
* written as-is? Is it already a line of space-separated variables?
*
* In any case, this is where you already have the words; so store them in
* the vector here as well.
*/
while (getline(f1, text_line))
{
string word;
istringstream text_stream(text_line);
while (text_stream >> word)
{
f0 << word << " ";
}
f0 << "\n";
}
f0.close() // Forgot your semi-colon
// Left f1 open, that's bad practice
ifstream file("intermediate.txt");
vector<string> code;
string line;
/*
* I would hope you felt that reading from a file, writing to a new file,
* closing both files, opening the new file, and reading from the new file
* into the vector was wasteful.
*/
while (getline(file, line, '\n'))
{
code.push_back(line);
}
for (auto it : code)
{
cout << it << "\n";
}
}
The most immediate issue with your original question was that you tried to open the same file in two different streams. The second time, the file failed to open, but because you never check if you actually opened the file, you assumed everything worked fine, but it didn't, which brought you here.
However, there is a better way.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::string inputFileName;
std::cout << "Enter the Input File Name: ";
std::cin >> inputFileName;
// Always check that you successuflly opened the file.
std::ifstream fin(inputFileName);
if (!fin) {
std::cerr << "Error opening: " << inputFileName << ". Exiting...\n";
return 1;
}
std::ofstream fout("intermediate.txt");
if (!fout) {
std::cerr << "Error opening: intermediate.txt. Exiting...\n";
return 2;
}
std::vector<std::string> code;
std::string text_line;
while (std::getline(fin, text_line)) // You've read the line
{
std::string word;
std::istringstream text_stream(text_line);
while (text_stream >> word) {
fout << word << " ";
}
fout << "\n";
code.push_back(text_line); // Just store it while you have it
}
fin.close(); // Best practice is to close a file as soon as you're done
fout.close(); // with it. Don't hog resources.
for (const auto& it : code) // Avoid making copies
{
std::cout << it << "\n";
}
}
The while loop, where you read the lines that you want to store in the vector, now writes to your file and stores the lines into the vector. We also now check whether we successfully opened files, and we close the file streams as soon as we're done with the file so as to not keep it locked for no good reason.
A good next step for improving this program a bit more would be to avoid asking the user for a file name. Instead, take it as an argument to main(). That way, someone only has to type ./a.out input.txt on the command line and the program will do the job automatically.
Filling an STL list with data from a text file fails.
Lexicon::Lexicon(const string &fileName) {
string tmp;
ifstream readFile;
readFile.open(fileName.c_str());
if (readFile.is_open()) {
cout << "File Is Open" << endl;
while (readFile >> tmp) {
list<string>::const_iterator i;
for (i = Words.begin(); i != Words.end(); ++i) {
Words.push_back(tmp);
}
readFile.close();
}
} else
{
cout<<"File Is NOT Open"<<endl;
}
}
string fileName = "wordsScrambled1.txt"; // in the main
Lexicon hello(fileName);
The program fails with the message "file is NOT open" and exits with code 0.
Before this question gets closed due to mcve, I wanted to point out some of the mistakes you're making. The first is obviously a path or permissions issue i.e. you are unable to open the input file. Once you get past that, you have likely made a mistake in your parsing of the file. You assume that all the characters between " " represent a word. This could be the case for all except the last word in the line. So you're better off using std::getline and parsing that with std::istringstream. Finally, like Sam pointed out in the comments section, you have a for loop that can't reasonably meet it's exit criteria before crashing. Just push_back the current element and move on to the next. Here is a quick example.
Lexicon::Lexicon(const std::string &fileName)
{
std::ifstream readFile(fileName.c_str());
if (readFile.is_open())
{
std::string line;
while (std::getline(readFile, line))
{
std::istringstream iss(line);
std::string word;
while (iss >> word)
{
Words.push_back(word);
}
}
readFile.close();
}
else
{
std::cout << "File Is NOT Open" << std::endl;
}
}
I'm having trouble figuring out how to read a file line by line into different data type vectors. Is there a way to do this with inFile >> ? My code is below. Thanks in advance!
void fileOpen()
{
fstream inFile;
inFile.open(userFile);
// Check if file open successful -- if so, process
if (!inFile.is_open()) {cout << "File could not be opened.";}
else
{
cout << "File is open.\n";
string firstLine;
string line;
vector<char> printMethod;
vector<string> shirtColor;
vector<string> orderID;
vector<string> region;
vector<int> charCount;
vector<int> numMedium;
vector<int> numLarge;
vector<int> numXL;
getline(inFile, firstLine); // get column headings out of the way
cout << firstLine << endl << endl;
while(inFile.good()) // while we are not at the end of the file, process
{
while(getline(inFile, line)) // get each line of the file separately
{
for (int i = 1; i < 50; i++)
{
inFile >> date >> printMethod.at(i);
cout << date << printMethod.at(i) << endl;
}
}
}
}
}
Before you use vector.at(i) in your case you should be sure that your vector is long enough cause at will generate out of range exception. As I can see from your code your vector printMethod contains no more than 50 elements so you can resize vector printMethod before use e.g.
vector<char> printMethod(50);
or
vector<char> printMethod;
printMethod.resize(50);
If you're planning to use a variable number of elements more than 50 you should use push_back method like #Phil1970 recommended e.g.
char other_data;
inFile >> date >> other_data;
printMethod.push_back(other_data);
I am trying to read lines of a file (cityName, hiTemp, loTemp) into a struct array. I was able to use >> to read the first several lines until I hit a city with a space in it's name.
I then tried using getline() to read the lines, but then my while loop stopped working.
I have no clue why this would happen.
int LoadData()
{
int count = 0;
string path;
cout << "Specify the input file path: ";
ifstream inFile;
cin >> path;
inFile.open(path.c_str());
if (!inFile.is_open())
{
cout << "Error - could not open file: " << path;
return (-1);
}
else
{
while (!inFile.eof())
{
cities[count].city = "";
getline(inFile, cities[count].city);
if (cities[count].city.length() == 0)
{
break;
}
char comma;
inFile >> (cities[count].high) >> comma >> cities[count].low;
cout << cities[count].city << " " << cities[count].high << " " << cities[count].low << endl;
count++;
}
inFile.close();
inFile.clear(std::ios_base::goodbit);
return count;
}
}
while (!inFile.eof())
For getting every line in the file, you should use:
while(getline(inFile, cities[count].city)) {
// ...
This works and is recommended over using the .eof() method.
You can also use this in your if-statement:
if (!getline(inFile, str))
break;
As an aside, you can read this site:
Why is “while ( !feof (file) )” always wrong? - StackOverflow post
It gives insight into why using the .eof() is not the preferred method to use in a while loop to check whether the end-of-file has been reached.
Use getline as loop condition. You can also replace the second read with a getline too and use a stringstream to parse it.
#include <sstream>
// ...
while(getline(inFile, cities[count].city)) {
if (cities[count].city.empty()) break;
// read next line with high and low values
string str;
if (!getline(inFile, str)) break; // error in file format
stringstream ss(str);
char comma;
ss >> cities[count].high >> comma >> cities[count].low; // parse it
}
Those are the parts of the code I have:
ifstream inFile;
inFile.open("Product1.wrl");
...
if (!inFile.is_open()){
cout << "Could not open file to read" << endl;
return 0;
}
else
while(!inFile.eof()){
getline(inFile, line);
cout << line << endl; //this statement only to chech the info stored in "line" string
if (line.find("PointSet"))
inFile >> Point1;
}
The output shows me the same string over and over again. So this means that the cursor inside the file does not proceed and getline reads the same line.
What might be the problem of this odd behavior?
If this is relevant:
The file does open as a .txt file and contains the exact information I need.
Okay I figured the problem:
Even after first eteration the return value of line.find("PointSet")is: 429467295... while my line string contains only one letter "S". Why?
Change
while(!inFile.eof()){
getline(inFile, line);
to
while( getline(inFile, line) ) {
I don't know why people get bitten by eof() quite so often, but they do.
Mixing getline with >> is problematic, because the >> will leave a '\n' in the stream, so the next getline will come back empty. Change that to use getline as well.
if (line.find("PointSet")) isn't what you want either. find returns the position in the string, or std::string::npos if it wasn't found.
Also, you can change
ifstream inFile;
inFile.open("Product1.wrl");
to
ifstream inFile ("Product1.wrl");
Here's a version showing the reads:
class Point
{
public:
int i, j;
};
template <typename CharT>
std::basic_istream<CharT>& operator>>
(std::basic_istream<CharT>& is, Point& p)
{
is >> p.i >> p.j;
return is;
}
int main()
{
Point point1;
std::string line;
while(std::getline(std::cin, line))
{
std::cout << line << '\n'; //this statement only to chech the info stored in "line" string
if (line.find("PointSet") != std::string::npos)
{
std::string pointString;
if (std::getline(std::cin, pointString))
{
std::istringstream iss(pointString);
iss >> point1;
std::cout << "Got point " << point1.i << ", " << point1.j << '\n';
}
else
{
std::cout << "Uhoh, forget to provide a line with a PointSet!\n";
}
}
}
}