So I am trying to copy a word by word from file1 to file2 , but my code fails in opening file2 (the output file)
void myFile::printWords(string inFile, string outFile)
{
ifstream file;
ofstream file2;
file.open(inFile);
file2.open(outFile);
if (!file.is_open() && !file2.is_open()){
string word;
while (!file.eof()){
file >> word;
file2 << word << '\n';
}
}
else{
cout << "error" << endl;
}
file.close();
file2.close();
}
Any idea why?
Note that you only copy words, if both files failed to open, not if both of them succeeded to open:
if (!file.is_open() && !file2.is_open()){
Replace it with:
if (file.is_open() && file2.is_open()){
if (!file.is_open() && !file2.is_open())
Means if file is not open and file2 is not open. So you will try to read from the files if they are not open and is not you execute cout << "error" << endl;.
Your if condition should be
if (file.is_open() && file2.is_open())
Also if you want to copy one file to another than you can use
file2 << file.rdbuf();
Instead of a while loop.
Problem 1
if (!file.is_open() && !file2.is_open()){
It should be
if (file.is_open() && file2.is_open()){
Problem 2
while (!file.eof()){
file >> word;
file2 << word << '\n';
}
That is wrong. It should be:
while ( file >> word ){
file2 << word << '\n';
}
To understand why, see Why is iostream::eof inside a loop condition considered wrong?.
The tests of the form !file.is_open() shouldn't have the not operator and could be simplified even more by relying on the operator bool() member function. It's also rarely correct to loop on the eof() condition.
Taking those two things in mind I've rewritten your function, I think it's simpler and more correct this way.
void myFile::printWords(const string &inFile, const string &outFile)
{
ifstream file(inFile);
ofstream file2(outFile);
if (file && file2) {
string word;
while (file >> word) {
file2 << word << '\n';
}
} else {
cout << "error" << endl;
}
}
Note: the streams will be closed automatically when they're destroyed at the end of this function.
if (!file.is_open() && !file2.is_open())
if file is not open and file2 is not open
this logic will not copy file to file2 if your testing to see if both files are not open.
Related
I'm trying to write a program that replaces a specific number with an 'x' character. The task requires every number to be in its own line, but it seems like '\n' is causing the read/write pointers to behave out of this world. Here's a picture of the output.
My questions are:
why are the pointers behaving this way?
How far do I need to move the write pointer backwards to overwrite a line to make this work?
is there an easier workaround?
Here's my code:
void input(int n)
{
fstream file;
file.open("numbers.txt", ios::out);
while(n --> 0)
{
file << n;
file << '\n';
}
file.close();
}
void read()
{
fstream file;
string tmp;
file.open("numbers.txt", ios::in);
while(true)
{
getline(file,tmp);
if(file.eof())
break;
cout << tmp << endl;
cout << "tellg: " << file.tellg() << " tellp: " << file.tellp() << endl;
}
file.close();
}
void replace()
{
fstream file;
string tmp;
file.open("numbers.txt", ios::in | ios::out);
while(true)
{
file >> tmp;
if(tmp == "6")
{
//cout << file.tellg() << endl;
file.seekp(file.tellg() - tmp.length()-1);
file << "x";
}
if(file.eof())
break;
}
file.close();
}
int main()
{
input(10);
replace();
read();
return 0;
}
Since you open your file in text mode, you need to account for the potential that the underlying stream may use a line end sequence (\r\n) rather than just a \n. I guess, this is the primary problem. The easiest remedy is probaly to open the file in binary mode:
file.open("numbers.txt", std::ios_base::binary | std::ios_base::in | std::ios_base::out);
That said, since you switch from writing to reading without intervening seek, your code is undefined behavior, i.e., anything can happen. You should seek to the current location between writing and reading.
Personally, I'd refrain from rewriting files in-place. It generally gets unnecessary trick. If I were to rewrite files in place, I'd use seekg() to get the current position before a read, saving the position and restoring it prior to the write (I essentially never use the seek operations, i.e., I may have got the signatures wrong):
for (std::streampos pos = (in >> std::ws).tellg();
in >> tmp; pos = (in >> ws).tellg()) {
if (need_to_overwrite) {
in.seekp(pos);
// ...
in.seekg(0, std::ios_base::cur);
}
}
The use of in >> std::ws is to make sure that whitespace is skipped before storing the position.
Also note that your check for file.eof() is wrong: the last line is processed twice. When reading from a file the result shall be tested before using the read string, e.g.:
while (in >> tmp) {
// ...
}
I have created a function to write some data on a text file, and it works fine. I created another function to read in all the content of the file, and print it out for me! But, it is not working for some reason. Could any one help please?
This is my function:
void myClass::displayFile() {
char line[LINE]; //to hold the current line
file.open("data.txt", ios::app);
//keep reading information from the file while the file is open and has data
while (!file.fail() && !file.eof()) {
int lineSize; //to loope through each line
file.getline(line, LINE);
lineSize = strlen(line);
//loop through the line to print it without delimiters
for (int i = 0; i < lineSize; ++i) {
if (line[i] == ';') {
cout << " || ";
} else {
cout << line[i];
}
}
}
file.close();
file.clear();
if (file.fail()) {
cerr << "Something went wrong with the file!";
}
}
Note: The function compiles and the loop is accessible, but the line string is empty.
This is the writing function:
void myClass::fileWriter() {
file.open("data.txt", ios::app);
file << name << ";" << age << ";" << "\n";
file.close();
file.clear();
}
Silly me, the cause of your problem was staring me right in the face from the beginning, and it's the app open-mode that's the problem. It is to open the file in write mode, which means you can't read from it.
And even if you could read from the file, the cursor is placed ad the end of the file the eofbit flag would have been set inside the first iteration anyway.
If you want to read from a file, then either use std::ifstream which automatically sets the in mode if you don't specify a mode, or you have to explicitly set the in mode when opening.
I'm trying to write a function that automatically formats XML-Strings; but I'm already failing when I try to read text from a file and write it into another one.
When I use my function sortXMLString()
bool FormatXML::sortXMLString()
{
string XMLString;
ifstream fin("input.txt");
fin.open("input.txt", ios::in);
ofstream fout("output.txt");
fout.open("output.txt", ios::out);
if (fin.is_open() && fout.is_open())
{
if (fin.good()) cout << "good" << endl;
if (fin.fail()) cout << "fail" << endl;
if (fin.bad()) cout << "bad" << endl;
while (getline(fin, XMLString))
{
//TODO: Formatting
fout << &XMLString << endl;
}
fin.close();
fout.close();
}
else return false;
return true;
}
I will get the output "fail", but the function never enters the while-loop. The function returns true.
It doesn't matter what I write into my input.txt (a single letter, a single number, multiple lines of text or even nothing), the failbit will always be set before getline can even be reached.
Why is this/ how can I properly read out of my file?
ifstream fin("input.txt"); will open the file with fin as stream object why calling open member function again ? same goes for fout object too.
Calling open on an already open stream fails, meaning the failbit flag is set to true.
Just open once
ifstream fin("input.txt");
ofstream fout("output.txt");
I need to know if you can easily get the number of data entries in another file and save that number in the original file. Need a program that will process the other file no matter how many entries are in it. Hope that makes any sense.
Your question is very poorly worded but I think you are looking for getline. This function can parse an input file based on the newline character (default behaviour) or based on a user provided delimiter:
int entryCount = 0;
std::string currentLine;
std::ifstream inFile( "in.txt" );
std::ofstream outFile;
if (inFile) // short for inFile.good())
{
while (std::getline( inFile, currentLine))
{
++entryCount;
// Do your processing
}
inFile.close();
outFile.open( "out.txt" );
outFile << "End of file. " << entryCount << " entries read." << std::endl;
outFile.close();
}
else
std::cout << "oops... error opening inFile" << std::endl;
I am trying to read from file:
The file is multiline and basically i need to go over each "word". Word being anything non space.
Sample input file would be:
Sample file:
test 2d
word 3.5
input
{
test 13.5 12.3
another {
testing 145.4
}
}
So I tried something like this:
ifstream inFile(fajl.c_str(), ifstream::in);
if(!inFile)
{
cout << "Cannot open " << fajl << endl;
exit(0);
}
string curr_str;
char curr_ch;
int curr_int;
float curr_float;
cout << "HERE\n";
inFile >> curr_str;
cout << "Read " << curr_str << endl;
The problem is when it reads new line it just hangs. I read everything before test 13.5
but once it reaches that line it doesnt do anything.
Anyone can tell me what I am doing wrong?
Any better suggestion on how to do this???
I essentially need to go through file and go one "word" (non white char) at the time.
I
Thanks
You open a file 'inFile' but are reading from the 'std::cin' any particular reason?
/*
* Open the file.
*/
std::ifstream inFile(fajl.c_str()); // use input file stream don't.
// Then you don't need explicitly specify
// that input flag in second parameter
if (!inFile) // Test for error.
{
std::cerr << "Error opening file:\n";
exit(1);
}
std::string word;
while(inFile >> word) // while reading a word succeeds. Note >> operator with string
{ // Will read 1 space separated word.
std::cout << "Word(" << word << ")\n";
}
Not sure how "in the spirit" of the iostream library this is, but you could do it with unformatted input. Something like:
char tempCharacter;
std::string currentWord;
while (file.get(tempCharacter))
{
if (tempCharacter == '\t' || tempCharacter == '\n' || tempCharacter == '\r' || tempCharacter == ' ')
{
std::cout << "Current Word: " << currentWord << std::endl;
currentWord.clear();
continue;
}
currentWord.push_back(tempCharacter);
}
Does that work?