Why does ofstream sometimes create files but can't write to them? - c++

I'm trying to use the ofstream class to write some stuff to a file, but all that happens is that the file gets created, and then nothing. I have some simply code here:
#include <iostream>
#include <fstream>
#include <cstring>
#include <cerrno>
#include <time.h>
using namespace std;
int main(int argc, char* argv[])
{
ofstream file;
file.open("test.txt");
if (!file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
for (int i = 0; i < 10; i++) {
file << i << "\t" << time(NULL) << endl;
}
file.flush();
file.close();
return 0;
}
When I create a console application, everything works fine, so I'm afraid this code is not completely representative. However, I am using code like this in a much larger project that - to be honest - I don't fully understand (Neurostim). I'm supposed to write some class that is compiled to a dll which can be loaded by Neurostim.
When the code is run, "test.txt" is created and then "No error!" is printed, as this is apparently the output from strerror. Obviously this is wrong however. The application runs perfectly otherwise, and is not phased by the fact that I'm trying to write to a corrupted stream. It just doesn't do it. It seems to me like there is no problem with permissions, because the file is in fact created.
Does anyone have any ideas what kind of things might cause this odd behavior? (I'm on WinXP Pro SP3 and use Visual C++ 2008 Express Edition)
Thanks!

Just a thought :- in your real code are you re-using your stream object?
If so, you need to ensure that you call clear() on the stream before re-using the object otherwise, if there was a previous error state, it won't work. As I recall, not calling clear() on such a stream would result in an empty file that couldn't be written to, as you describe in your question.

ofstream file;
file.open("test.txt");
Just a nit: you can combine that into a single line. ofstream file("test.txt");
if (file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
Your test is backwards. If file is true, it's open and ready for writing.
Also, I wouldn't count on strerror() working correctly on Windows. Most Windows APIs don't use errno to signal errors. If your failure is happening outside the C/C++ run-time library, this may not tell you anything interesting.

UPDATE Thinking more about this, failing to open a file via fstreams is not guaranteed to set errno. It's possible that errno ends up set on some platforms (espeically if those platforms implement fstream operations with FILE* or file descriptors, or some other library that sets errno) but that is not guaranteed. The official way to check for failure is via exceptions, std::io_state or helper methods on std::fstream (like fail or bad). Unfortunately you can't get as much information out of std::streams as you can from errno.
You've got the if statement wrong. operator void* returns NULL (a.k.a. false) if the file is not writable. It returns non-zero (a.k.a. true) if the file is writeable. So you want:
if (!file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
Or:
if (!file.good()) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}

Related

How to open a text file

I am trying to open a text file, and the code below is my attempt:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
std::ifstream file;
file.open("InputFile.txt");
std::string fileOutput;
if (file.is_open())
{
while (!file.eof())
{
file >> fileOutput;
std::cout << fileOutput << std::endl;
}
}
else
{
std::cout << "File failed to open" << std::endl;
}
file.close();
return 0;
}
The text file is located on my desktop, and it only contain two integers.
Whenever I run the code above, it will show me the "file failed to open" message. I am completely new to c++, so I really don’t have any idea why my code is not working. So any comments would be appreciated.
The text file is located on my desktop
So where is your C++ source file, is it located in my desktop as well?
Note this code file.open("InputFile.txt"); tries to open the InputFile.txt in the current folder, that means it only works if both C++ source file and your text file are in the same folder. That seems to be your problem.
Like #ShadowRanger's this comment, the existing answers are both inaccurate. The argument for file.open() needs to either 1. reflect the relative location of the text file in relation to the current working directory (where you are calling the executable from), or 2. give the absolute location of the text file on the disc.
I suggest the following solution:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "incorrect number of inputs" << "\n";
std::cout << "correct usage: this_executable.exe file_location" << "\n";
return -1;
}
std::ifstream file;
file.open(argv[1]);
std::string fileOutput;
if (file.is_open())
{
while (file >> fileOutput)
{
std::cout << fileOutput << std::endl;
}
}
else
{
std::cout << "File "<< argv[1] <<" failed to open" << std::endl;
}
file.close();
return 0;
}
This solution takes the file's address info out of the code. With this solution, when you call your executable, the file's address(directory path + file name) is given to the executable at run-time rather than compile-time. Now, you'd run the executable like:
C:\path_to_your_exe>my_executable.exe C:\path_of_your_txt_file\InputFile.txt
The benefits of this approach are:
You can change the file's name / path without having to recompile the code;
On the commandline, it is easier to check that the target file's address is correct by tab completion
Also note:
As #ShadowRanger also pointed out the Why is “while ( !feof (file) )” always wrong? issue which I was not aware of.
If you are wondering what argv[1] means, see this guide for more information on commandline arguments for C++. You also want to make sure to catch situations when the user did not specify an input (meaning argv[1] is invalid, thus the argc != 2)
Unless the file you are opening and your executable are in the same directory, the same message will be printed since it will search for the file in the current working directory. You can specify the absolute path to the file on your desktop using %USERPROFILE%\\Desktop\\InputFile.txt or any other environmental variable that maps the absolute path of a disk, from which your file can be found.

fstream test program crashes for some reason

I have been playing around with the fstream class in C++ to see if I am able to write some data to a text file(.txt). According to what I know, If the program tries to write to a file that does not exist then it would automatically create that file, am I wrong? This program is very simple and does not give me any compiler errors which means it builds fine. However for some reason it crashes when I run it.
Here is my code:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream>
std::fstream* myFile;
int main()
{
int age = 15;
std::string myName = "Javier Martinez";
std::string friendsName = "David Lyn";
//Backslash is a special character, use double backslash or forward slash instead.
myFile->open("C:/Users/NIKE/Desktop/data.txt");
if (myFile->fail())
{
std::cerr << "File was unable to be opened.";
}
*myFile << age << "\n";
*myFile << myName << "\n";
*myFile << friendsName << "\n";
myFile->close();
std::cout << "File was successfully written to with the data";
return 0;
}
Any help is appreciated. Thank you in advance.
NOTE: I am using the GNU GCC compiler with Code::Blocks IDE
myFile is uninitialized. Check it.( Allocate memory) or simply use fstream.
Your problem stems from the line:
std::fstream* myFile;
You only declared a pointer to a stream object, which is initialized to nullptr by reason of it being in the global scope. The fact that you tried accessing a non-existent object (invalid) through it, you invoked what is known as Undefined Behavior.
You do not need to allocate stream objects on the heap, rather, do:
std::fstream myFile;
On a side Note: Check your program control flow:
if (!myFile)
{
std::cerr << "File was unable to be opened.";
}
else{
myFile << age << "\n";
myFile << myName << "\n";
myFile << friendsName << "\n";
}

Check whether file name already exists in a folder or not?

In C++ I need to check whether a entered file name exists in that folder or not. I'm writing code for Linux, using the g++ compiler.
please help guys :)
I saw this code somewhere on net for my problem but I strongly feel it wont serve my purpose:
ofstream fout(filename);
if(fout)
{
cout<<"File name already exists";
return 1;
}
You can do this by testing with an ifstream, but there is a subtle difference between using that and the C level stat() interface.
#include <cerrno>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
using namespace std;
int main (int argc, const char *argv[]) {
if (argc < 2) {
cerr << "Filepath required.\n";
return 1;
}
ifstream fs(argv[1]);
if (fs.is_open()) {
fs.close();
cout << "ifstream says file exists.\n";
} else cout << "ifstream says file does not exist.\n";
struct stat info;
if ((stat(argv[1], &info)) == -1) {
if (errno == ENOENT) cout << "stat() says file does not exist.\n";
else cout << "stat() says " << strerror(errno) << endl;
} else cout << "stat() says file exists.\n";
return 0;
}
If you run this on a file that exists and you have read permission on, you'll get the same answer both ways.
If you run this on a file that does not exist, you get the same answer both ways.
If you run this on a file that exists but you do not have read permissions on, you'll get two different answers. fstream will say the file does not exist, but stat() will say it does. Note that if you run ls in the same directory, it will show the file, even though you cannot read it; it does exist.
So if the last case is not significant -- i.e., a file you can't read might as well not exist -- then use the ifstream test. However, if it is important, then use the stat() test. See man 2 stat (the 2 is important) for more, and remember, to use it you need:
#include <cerrno>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
cerrno is required to check errno if stat() fails, which can happen. For example, if read permission on a directory in the path is denied, then stat() will fail and errno will be equal to EACCES; if you try it with the above program you'll get stat() says Permission denied. This does not mean the file exists. It means you can't check whether it exists or not.
Beware, if you have not used errno before: You must check immediately on a failed call, before you make any others which may set it differently. It is, however, thread safe.
If you want to be cross-platform and C++'y I recommend the Boost Filesystem library.
For your purposes I think something similar to this Boost sample code
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
path p (argv[1]); // p reads clearer than argv[1] in the following code
if (exists(p)) // does p actually exist?
{
if (is_regular_file(p)) // is p a regular file?
cout << p << " size is " << file_size(p) << '\n';
else if (is_directory(p)) // is p a directory?
cout << p << "is a directory\n";
else
cout << p << "exists, but is neither a regular file nor a directory\n";
}
else
cout << p << "does not exist\n";
return 0;
}
would do the job.
Maybe what you want is fstat:
http://codewiki.wikidot.com/c:system-calls:fstat

Why doesn't my function produce output

I'm doing a C++ assingment for a class and I haven't used C++ in a decade so this might be something I'm missing that is simple; however ,I can't seem to figure it out.
I have a class I defined with a function that is producing no output; it looks like it's not even running and I don't have a clue why. Could someone point out my problem to me?
Issue: cout from the function getwords of the class readwords doesn't display any results.
Here is my class:
class readwords {
private:
char c;
//string aword;
public:
void getwords(std::istream& file) {
cout << "I got here" << std::flush;
/*while(file.good()) {
cout << "I got here\n";
c = file.get();
if(isspace(c)) cout << "\n"; //continue;
if(isalnum(c)) {
cout << c; //aword.insert(aword.end(),c);
}
}
*/
}
};
Which is being called from my main:
#include <fstream>
#include <stdlib.h>
#include "lab1.h"
using namespace std;
readwords wordsinfile;
words wordslist;
int main ( int argc, char *argv[] )
{
if ( argc != 2 ) {
// Looks like we have no arguments and need do something about it
// Lets tell the user
cout << "Usage: " << argv[0] <<" <filename>\n";
} else {
// Yeah we have arguements so lets make sure the file exists and it is readable
ifstream ourfile(argv[1]);
if (!ourfile.is_open()) {
// Then we have a problem opening the file
// Lets tell the user and exit
cout << "Error: " << argv[0] << " could not open the file. Exiting\n";
exit (1);
}
// Do we have a ASCII file?
if (isasciifile(ourfile)) {
cout << "Error: " << argv[0] << " only can handle ASCII or non empty files. Exiting\n";
exit(1);
}
// Let ensure we are at the start of the file
ourfile.seekg (0, ios::beg);
// Now lets close it up
ourfile.close();
}
// Ok looks like we have past our tests
// Time to go to work on the file
ifstream ourfile2(argv[1]);
wordsinfile.getwords(ourfile2);
}
Thank you for any help you can provide.
Try to use a debugger. Most IDEs (NetBeans, Code::Blocks, etc) provide an interactive interface with gdb.
I just compiled and ran your code, but nothing wrong with the code itself,
except that I needed to include to use the 'cout' method.
"I got here" has been successfully displayed in my ubuntu machine.
What is your execution environment? You should check it first.
The problem appears to be redefining my own class. When actually coding the function I needed to use:
in readwords::countwords(std::istream& file) {
....
}
Once doing this output produced fine.

Try to write char[] to a text file

I trying to write a char[256] to a text file. Below is my current work:
fstream ofs;
ofs.open("c:\\myURL.txt");
ofs.write((char*)testDest,256);
ofs.close();
It still does not work.
here is the error:
error C2440: 'type cast' : cannot convert from '' to 'char *'
update:
so far, here is my progress attempt, the code can compile, but when running, my program suddenly terminated.
ofstream stream;
CBar *a;
switch(uMessage) {
case WM_PAINT:
return bar->OnPaint();
case WM_ERASEBKGND:
return 1;
case WM_LBUTTONDOWN: //wira
if (!bar->OnClick(wParam, lParam)) {
stream.open("C:\\myURL.txt");
stream << a->testDest << endl; // if I replace `a->testDest` with "testword" string, my prgrom does not terminated. Why?
return 0;
}
break;
Several things wrong or "not good" in your code:
You never check if the open fails.
You use clunky write functions.
You don't check if your write is succesful (not quite necessary if you're kind of sure it will work).
This will give you more info if something fails:
#include <fstream>
using std::ofstream;
#include <iostream>
using std::cout;
using std::endl;
int main()
{
ofstream stream;
char charArray[] = "Some stuff in a char array.";
stream.open("C:\\myurl.txt");
if( !stream )
cout << "Opening file failed" << endl;
// use operator<< for clarity
stream << testDest << endl;
// test if write was succesful - not *really* necessary
if( !stream )
cout << "Write failed" << endl;
return 0;
}
My guess is that opening the file failed because you lack proper permissions. The above program will tell you where what fails.
UPDATE: To answer your second question: you do this:
CBar* a;
Which creates a pointer but leaves it unitiallized. You then want to dereference it to access its testDest data member, which obviously leads to a crash. You need to initialize your pointer (or don't use a pointer here, I see no reason to):
// Either this
CBar* a = new CBar(/*some arguments, or none, depending on CBar definition*/);
//...
cout << a->testDest << endl;
// Or this (better here in my opinion)
CBar a; // OK if there is a default constructor (one with no arguments);
//...
cout << a.testDest << endl;
Please read any good tutorial on c++. These are mistakes you make either when you've not slept for three days or if you don't understand the basic concepts of the language.
You need to pass to fstream, in open(), the kind of operation you're expecting to do: input, output, or even both. You should try with:
ofs.open( "c:\\myURL.txt", ios::out | ios::text);
Anyway, it would be better to use ofstream instead of a generic fstream:
ofstream ofs;
ofs.open( "c:\\myURL.txt", ios::text );
ofs.write( (char*)testDest, 256 );
ofs.close();
You forget that if someone is trying to check if file exists, then if it doesn't create the file you have to use fstream for your object so is to not have 2 different objects for open and write