C++: Why is ofstream not appending or creating new files? - c++

i have a little problem with ofstream. My main calls a certain class several times, each time with different parameters for testing purposes
ImageComparison* imco = new ImageComparison(queries[i], j, k, l);
Inside each instance i want a formatted output to a file, so i first tried this
ofstream ofs;
ofs.open("somepath" + params + ".txt");
ofs << "write results";
ofs.close();
I expected that ofstream would create several files, due to different params and therefor different filenames, and write something into it. But it appears that it's always overwriting the former file and just saving the last instance.
Afterwards i tried to use one file over and over again and appending new lines, since this would be a better solution for my case
ofstream ofs;
ofs.open("somename.txt", ofstream::out | ofstream::app);
ofs << "write params";
ofs << "write results in same line";
ofs << endl;
ofs.close();
In this case it appears that it's not appending new lines, instead it overwrites the former line and in the end i just have the results of the last instance.
Please enlighten me, i don't have any ideas whats wrong here.
I appreciate any suggestions/solutions :)
EDIT: here is concrete case:
main:
vector<string> queries = {"apple","banana","book"...};
for(int i=0; i<18; i++) {
//if(i==1) break;
for(int j=0; j<3;) {
//if(j==2) break;
for(int k=10; k<800;) {
//if(k==400) break;
for(int l=50; l<600;) {
ImageComparison* imco = new ImageComparison(queries[i], j, k, l);
imco->DoImCo();
delete imco;
}
}
}
}
ImageComparison.cc:
string bloo = "../ImageData/" + m_object_type + "/" + m_object_type + "metric=" + to_string(m_metric) + ",hessian=" + to_string(m_hessian) + ",words" + to_string(m_number_of_words) + ".txt";
ofstream ofs;
ofs.open(bloo.c_str(), ofstream::out | ofstream::app);
for(int i=0; i<image_names.size(); i++) {
if(similarity_of_one[i] < similarity_average) {
ofs << " x";
}else{
ofs << " v";
}
}
ofs << endl;
ofs.close();
EDIT2: forgot parameter increase inside the "for's" but not important i think

Did you try starting a new project with only this part of your example code? Doesn't it append new lines for you?
Blockquote
ofstream ofs;
ofs.open("somename.txt", ofstream::out | ofstream::app);
ofs << "write params";
ofs << "write results in same line";
ofs << endl;
ofs.close();
Try to use ofstream::app only, it will automatically create new file for you. Frankly, I don't see any problem with the above code.
(Sorry I never made an answer. It looks lame :( )

Finally, i found something. It seems that there were a problem with the name. After using a constant name like "../Test.txt" it worked fine, sill don't know why but the problem is gone. Big thx for all your suggestions.

Related

Read from file, output in a new file, and compare outputs

I need a little bit help with my code. The first part of the code, was easy to create. Read from two textfiles -> Output in a new textfile.
My next step is to compare the both outputs line by line.
If the number is the same, the numbers stays.
If the number is different to the number of textfile2,
the number with be replaced.
Example:
Textfile1:
2221112221
1122221112
2222221111
1111111111
Textfile2:
2222221111
2211222212
1111111111
2221112222
Result that should happen on Textfile3:
(like I'm overlapping textfile2 on textfile1)
2222221111
2211222212
1111111111
2221112222
So I already researched for str.compare, but I'm not able to output the result as above stated. I don't know if this works with it.
if((line2.compare(0, line2.length(), line1)) == 0)
string line1, line2;
ifstream read1, read2;
read1.open("test.txt", ios::in);
read2.open("test2.txt", ios::in);
ofstream outFile("outputfile.txt", ios::out | ios::app);
if(!read1 || !read2){
cerr << "One file is missing" << endl;
exit(1);
}
else {
while(getline(read1, line1))
{
outFile << line1;
}
while(getline(read2, line2))
{
outFile << line2 << endl;
}
Thanks a lot guys!
iterate the strings and compare character vs. character? This would allow you to achieve what you're looking for.
This example obviously does not have exception handling (e.g. different string lengths):
std::string corn = "I eat Corn!";
std::string rice = "I eat Rice!";
int main()
{
for (size_t i = 0; i < corn.length(); i++)
{
if (corn[i] != rice[i])
{
rice[i] = corn[i];
}
}
std::cout << rice;
}

C++ ofstream writing variables into a text file

I wasn't able to find any obvious answers to this, and I'm pretty stumped.
Do I need to do something different when I want to write a variable string into a text document compared to what I need to do when I want to write just a set string into said document?
This code would properly write "set string" on 8 individual lines on newfile.txt (and create it).
string output_file = "newfile.txt"
ofstream file_object_2;
file_object_2.open(output_file, std::ofstream::out | std::ofstream::app);
string nextline;
for (int i = 0; i <= row_number; ++i)
{
file_object_2 << "set string" << "\n";
}
file_object_2.close();
return 0;
But this would leave the file completely empty, even if line_vector[i] itself has strings within it (and cout can print them)
string output_file = "newfile.txt"
ofstream file_object_2;
file_object_2.open(output_file, std::ofstream::out | std::ofstream::app);
string nextline;
for (int i = 0; i <= row_number; ++i)
{
nextline = line_vector[i];
file_object_2 << nextline << "\n";
}
file_object_2.close();
return 0;
I tried to look at the documentation and do it the same way as they had done, but I'm having no success here. Obviously because of my own failure, but I just can't figure out where I'm in the wrong here.
The only difference with those two codes are in the lines where I'm trying to write into the document
file_object_2 << nextline << "\n";
vs
file_object_2 << "set string" << "\n";
main() that I tried to trim down so it has less dynamic functionality (no manual inputs) but still does not work:
The text file "a.txt" has just a couple of lines of random strings
[a.txt]
("Yogi has a best friend too
Boo Boo, Boo Boo
Yogi has a best friend too
Boo Boo, Boo Boo Bear
Boo Boo, Boo Boo Bear
Boo Boo, Boo Boo Bear
Yogi has a best friend too
Boo Boo, Boo Boo Bear")
And the function itself
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main() {
string input_file = "a.txt";
vector<string> line_vector;
string output_file = "output.txt";
// reads from the original text file. Included in the example because I might
// be constructing the vector in a stupid way and this is where it happens
int row_number = 0;
string line;
while (getline(file_object, line) )
{
cout << line << endl;
line_vector.push_back(line);
++row_number;
}
file_object.close();
// writing onto a new file starts, this is where I'd assume the problem is
ofstream file_object_2;
file_object_2.open(output_file, std::ofstream::out | std::ofstream::app);
string nextline;
for (int i = 0; i <= row_number; ++i)
{
nextline = i + " " + line_vector[i];
file_object_2 << nextline << "\n";
}
file_object_2.close();
return 0;
}
This is broken:
i + " " + line_vector[i]
You meant to_string(i) + " " + line_vector[i], but you used + directly on i and "", which the compiler determines is operator+(int, const char*) which is pointer arithmetic, not a conversion of i to a string. Since the string in question only has one character (a NUL), adding 1 number results in a past-the-end pointer which can't be dereferenced, adding larger numbers is already undefined behavior.
The simplest fix would be to keep i separate from nextline, and write it to the file directly. Your loop body becomes:
{
nextline = line_vector[i];
file_object_2 << i << " " << nextline << "\n";
}
But it should also work to convert i to a string using std::to_string().
As a side note, the first snippet of code you claimed is broken (where nextline = line_vector[i];) actually is just fine. If you had bothered to test that you might have found the problem yourself.

c++ file pointers not working properly

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 Can't print out a file that I wrote on

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.

Writing CRC data to .txt file

This seems like it should be a basic C++ process, but I'm not familiar with the data output.
When I print the data without outputting to a text file, I get the correct values.
example: 00150017000 181
When printing to a text file, this is what I get:
11161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116
Here is my code:
ofstream myfile;
myfile.open("C:\\CRC.txt");
for (i = 0; i < 200; i++, id++)
{
myfile << sprintf(idstring, "%011d", id);
myfile << printf("%s %03d\n", idstring, computeCrc(idstring));
}
myfile.close();
Everything else works fine and I know the CRC is generated correctly. Just a matter of getting the correct output.
I was able to output the console screen to a text file by adding "> CRC.txt" to the Debugging Properties Command Arguments, but I just wanted to know how I could incorporate the ofstream method into this.
Thanks in advance.
You don't save to the file what you think you save. First you save the result of sprintf() function, which in your case is 11. Then you save the result of the printf() function which in your case is 11 + 1 (space) + 3 + 1 (\n) = 16. So the result is 200 times 1116.
What you wanted to do
char tempBuf[12];
ofstream myfile;
myfile.open("C:\\CRC.txt");
for (i = 0; i < 200; i++, id++)
{
sprintf(tempBuf, "%011d", id);
myfile << tempBuf << ' ';
sprintf(tempBuf, "%03d", computeCrc(tempBuf));
myFile << tempBuf << '\n';
}
myfile.close();
You are ouputing the return of sprintf() and printf() to the file. The returns of sprintf() and printf() are int and not the string you are creating. To output the string you need to change your code to
for (i = 0; i < 200; i++, id++)
{
sprintf(idstring, "%011d", id);
myfile << idstring;
myfile << computeCrc(idstring) << endl;
}