File won't open for writing - c++

I'm trying to write contents of datastructure to a file but for some reason file.is_open() returns false. Am I missing something? Printing should work fine as I tested it with cout.
std::ofstream file;
file.open(filename, std::ofstream::out | std::ofstream::trunc);
for(int i = 0; i < 1000; ++i) {
Candy* tmp = index[i];
for(; tmp; tmp = tmp->next){
if(file.is_open()){
file << tmp->ID << ";" << tmp->amount << ";" << tmp->location <<
}
else{
std::cout << "error" << std::endl;
}
}
file.close();
}

Could it be that your curly braces are mismatched?
You never close out of the scope of the first for loop, so you are closing the file on the first iteration of the loop.

Do you have the correct permissions to write to the file path? Do the does the path to the file actually exist?
You can check the errno to find out what went wrong.
#include <cerrno>
std::cout << "File error: " << strerror( errno ) << std::endl;

Related

Appending data to csv file, before last entry instead of after last entry. C++

Not easy to formulate that question, so I am sorry for any grief there..
I am writing to a csv file like this at the moment:
double indicators::SMACurrentWrite() {
if ( !boost::filesystem::exists( "./CalculatedOutput/SMAcurrent.csv" ) ) // std::cout << "Can't find my file!" << std::endl;
{
std::ofstream SMAfile;
SMAfile.open("./CalculatedOutput/SMAcurrent.csv");
SMAfile << "SMA" << endl << SMA[0] << endl; // .. or with '\n' at the end.
SMAfile.close();
}
else {
std::ofstream SMAfile;
SMAfile.open ("./CalculatedOutput/SMAcurrent.csv", ios::app); // Append mode
SMAfile << SMA[0] << endl; // Writing data to file
SMAfile.close();
}
return 0;
}
Each time the application runs, a new value is appended to the output file at the end:
SMA
32.325
I guess there is no way of just squeezing that new vector entry in there under the header( and over the number), but that is what I want to accomplish anyway.
So I guess I would have to read the existing output file back in,put it in a vector, and then replace the old file ? I started with smth like this:
double indicators::SMACurrentWrite() {
if ( !boost::filesystem::exists( "./CalculatedOutput/SMAcurrent.csv" ) ) // std::cout << "Can't find my file!" << std::endl;
{
std::ofstream SMAfile;
SMAfile.open("./CalculatedOutput/SMAcurrent.csv", ios::app);
SMAfile << "SMA" << endl << SMA[0] << endl; // .. or with '\n' at the end.
SMAfile.close();
}
else {
std::ofstream SMARfile("./CalculatedOutput/SMAReplacecurrent.csv");
std::ifstream SMAfile("./CalculatedOutput/SMAcurrent.csv");
SMARfile << SMA[0] << endl; // Writing data to file
SMARfile << SMAfile.rdbuf();
SMAfile.close();
SMARfile.close();
std::remove("./CalculatedOutput/SMAcurrent.csv");
std::rename("./CalculatedOutput/SMAReplacecurrent.csv","./CalculatedOutput/SMAcurrent.csv");
}
return 0;
}
...., but of course that just puts the new data in above the header like this :
32.247
SMA
32.325
..rather than this
SMA
32.247
32.325
I would rather this didn't become such a time- consuming exercise, but I appreciate any help on how I could get this done.
If you read in the first line from the input file you can use that to start the new file and it will leave the file pointer at the second line where the old data starts. Then you can write the new stuff like this:
if(!boost::filesystem::exists("./CalculatedOutput/SMAcurrent.csv"))
{
std::ofstream SMAfile;
SMAfile.open("./CalculatedOutput/SMAcurrent.csv", ios::app);
SMAfile << "SMA" << '\n' << SMA[0] << '\n';
SMAfile.close();
}
else
{
std::ofstream SMARfile("./CalculatedOutput/SMAReplacecurrent.csv");
std::ifstream SMAfile("./CalculatedOutput/SMAcurrent.csv");
// first read header from input file
std::string header;
std::getline(SMAfile, header);
// Next write out the header followed by the new data
// then everything else
SMARfile << header << '\n'; // Writing header
SMARfile << SMA[0] << '\n'; // Write new data after header
SMARfile << SMAfile.rdbuf(); // Write rest of data
SMAfile.close();
SMARfile.close();
std::remove("./CalculatedOutput/SMAcurrent.csv");
std::rename("./CalculatedOutput/SMAReplacecurrent.csv",
"./CalculatedOutput/SMAcurrent.csv");
}

IOS text file is empty after apparently successful writing

IN IOS app, module written in C++ I am writing my data (map of basic strings and integers) to a text file. Using following method:
bool Recognizer::saveMap(const char * s)
{
if(trainingData.model && !trainingData.model.empty()) {
const string filename = string(s);
std::ofstream file(s, ios_base::trunc );
try{
if(! file.is_open())
{
file.open(s);
}
for (map<String,int>::iterator it=trainingData.idMap.begin(); it!=trainingData.idMap.end(); ++it)
{
cout << it->second << " " << it->first << endl;
file << it->first << endl << it->second << endl;
}
file.close();
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
std::streampos fileLength = iosFileSize(s);
cout << "Saved map to: " << filename << " length: " << fileLength << endl;
return true;
}
return false;
}
My contains one entry and console output indicates that two lines: string, string representing number have been written to my file.
Subsequent opening file for reading and reading using getline or using stream operator indicates that file is empty:
bool Recognizer::loadMap(const char * s)
{
std::streampos fileLenght = iosFileSize(s);
std::ifstream file(s, ios::in);
try{
if(file.is_open())
{
string name;
string lineName;
string lineTag;
int tag;
int count = 0;
while(getline(file,name))
{
if(getline(file,lineTag))
{
tag = stoi(lineTag,0,10);
count++;
cout << tag << " " << name << endl;
trainingData.idMap[name]=tag;
trainingData.namesMap[tag]=name;
}
}trainingData.personsCount=count;
file.close();
}
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
cout << "Loaded map from: " << s << " lenght: "<< fileLenght << endl;
return true;
}
I also copied from one of stackoverflow answers method returning file lenght and using it to verify lenghth of the file after write operation:
std::streampos iosFileSize( const char* filePath ){
std::streampos fsize = 0;
std::ifstream file( filePath, std::ios::binary );
fsize = file.tellg();
file.seekg( 0, std::ios::end );
fsize = file.tellg() - fsize;
file.close();
return fsize;
}
The file path passed to saveMap and loadMap seems to be legit. With path that the app could not write to, attempt to write caused exception.
There are no errors returned by write operation but both, attempts to read and iosFileSize() indicate that file is empty.
I am not sure if i need call file.open() and file.close() or file is open and closed automatically when output stream is created and later goes out of scope.
I experimented with those with the same result ( call to file.is_open returns true so the block calling file.open() is skipped.
What am I doing wrong?
I appreciate all responses.
It does not seem like you call file.flush(); anywhere in Recognizer::saveMap() after writing to the file stream. std::ofstream::flush() saves changes you've made to the file. Add file.flush(); between when you make changes to the code and when you close the file. See if that remedies your issue.
I also had the same issue. Using file.flush() everytime after you insert to a file can save your file.
However if you insert something like this, say,
file << "Insert This"; You will need to add file.flush().
But some people have issues, like if you just insert file << "Insert This" << endl; , this works fine. The key point here is that, std::endl calls flush() everytime it is used internally. you can say it is a shortend form of "\n" + flush().
I believe from looking at your code that you are overwriting your data when you open the file in the second program you should be using something like this.
std::fstream fs;
fs.open ("test.txt", ios::app)
instead of doing the ios::in

ofstream/fstream simply will not work, no matter what solution is tried

Okay guys, I've tried everything I can think of. I'm passing in a file name into this function. A little context: hash_table is an already initialized and filled vector with key pairs, and the 'value' part of the pair is a Linked List that has the field "bucket_size". When I use cout to check if these fields are actually being accessed, they are; even the debugger lists them as being filed into the output stream. I have flush() and close() in there, but it doesn't write anything to the file. Returns true, indicating no errors in the stream. Anyone have nay ideas?
string line;
std::ofstream ofs;
if(ofs.is_open())
ofs.close();
ofs.open(filename);
if (ofs.is_open())
{
cout << "File Opened" << endl;
for (double i = 0; i < hash_table.capacity(); ++i)
{
ofs << "Bucket Number " << i;
if (hash_table[i].value != NULL)
ofs << " Bucket Size: " << hash_table[i].value->bucket_size << endl;
else
ofs << " Bucket Size: 0" << endl;
ofs.flush();
}
cout << "closing file stream" << endl;
ofs.flush();
ofs.close();
if (ofs.good())
return true;
else
return false;
}
else
{
cout << "File not opened" << endl;
return false;
}
}
You're almost certainly examining the wrong file. Remember that relative paths are relative to the working directory of the process, which is not necessarily the same as where the executable lives on disk.
I compiled and ran it by the console and now it works, with no edits made. It seems my IDE doesn't like something in the code. Regardless, thank you everyone for the response.s

C++ ios:fail() flag

I am trying to read a las file larger then 2GBs (about 15GBs) but ios::fail() flag becomes true in 345th byte. Here is the code below.
void Foo()
{
char* filename = "../../../../../CAD/emi/LAS_Data/AOI.las";
ifstream m_file (filename);
char c;
int count = 0;
if (m_file.is_open())
{
while ( m_file.good() )
{
m_file.get(c);
cout << c << endl;
count++;
}
// Check State
if(m_file.fail())
cout << "File Error: logical error in i/o operation." << endl;
if(m_file.eof())
cout << "Total Bytes Read: " << count << endl;
m_file.close();
}
else
{
cout << "File Error: Couldn't open file: " << endl;
}
}
And the output is:
...
File Error: logical error in i/o operation.
Total Bytes Read: 345
What am I missing?
I'm going to guess that you're using Windows. Windows has a quirk that a Control-Z marks the end of a text file, no matter how large the file actually is. The solution is to open the file in Binary mode.
ifstream m_file (filename, std::ios::binary);

Reading and appending from/to a file with std::fstream

I'm wondering why the following piece of code doesn't work, looks pretty straight-forward, am I making a mistake?
The result of this is: file created but empty, if I manually add lines those lines are showed with this code, but nothing else happens.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(){
fstream mfile("text.txt", ios_base::in | ios_base::out | ios_base::app);
mfile.seekg(ios_base::beg);
string line;
while( getline(mfile,line) ){
std::cout << line << "\n";
}
mfile.seekg(ios_base::end);
mfile << "Line 1\n";
mfile << "Line 2\n";
mfile << "---------------------------------\n";
mfile.seekg(ios_base::beg);
while( getline(mfile,line) ){
std::cout << line << "\n";
}
mfile.seekg(ios_base::end);
}
Couple of things:
When you are ready to write, you need to seekp() rather than seekg(), i.e.
mfile.seekp(ios_base::end);
Now, the problem here is that the getline() calls will set the stream flags (specifically eof), and as a result the stream is not ready for further operations, you need to clear the flags first!
try this:
string line;
mfile.seekg(ios_base::beg);
while( getline(mfile,line) ){
std::cout << line << endl;
}
mfile.seekp(ios_base::end); // seekp
mfile.clear(); // clear any flags
mfile << "Line 1" << endl; // now we're good
mfile << "Line 2" << endl;
mfile << "---------------------------------" << endl;
mfile.seekg(ios_base::beg);
while( getline(mfile,line) ){
std::cout << line << endl;
}
Also, use std::endl rather than "\n", this will trigger a flush of the buffers to the file at the OS's convinience...