ifstream: how to tell if specified file doesn't exist - c++

I want to open a file for reading. However, in the context of this program, it's OK if the file doesn't exist, I just move on. I want to be able to identify when the error is "file not found" and when the error is otherwise. Otherwise means I need to quit and error.
I don't see an obvious way to do this with fstream.
I can do this with C's open() and perror(). I presumed that there was a fstream way to do this as well.

EDIT: I've been notified that this does not necessarily indicate a file does not exist, as it may be flagged due to access permissions or other issues as well.
I know I'm extremely late in answering this, but I figured I'd leave a comment anyway for anyone browsing. You can use ifstream's fail indicator to tell if a file exists.
ifstream myFile("filename.txt");
if(myFile.fail()){
//File does not exist code here
}
//otherwise, file exists

I don't think you can know if "the file doesn't exist". You could use is_open() for generic checking:
ofstream file(....);
if(!file.is_open())
{
// error! maybe the file doesn't exist.
}
If you are using boost you could use boost::filesystem:
#include <boost/filesystem.hpp>
int main()
{
boost::filesystem::path myfile("test.dat");
if( !boost::filesystem::exists(myfile) )
{
// what do you want to do if the file doesn't exist
}
}

Since the result of opening a file is OS-specific, I don't think standard C++ has any way to differentiate the various types of errors. The file either opens or it doesn't.
You can try opening the file for reading, and if it doesn't open (ifstream::is_open() returns false), you know it either doesn't exist or some other error happened. Then again, if you try to open it for writing afterwards and it fails, that might fall under the "something else" category.

A simple way from http://www.cplusplus.com/forum/general/1796/
ifstream ifile(filename);
if (ifile) {
// The file exists, and is open for input
}

You can use stat, which should be portable across platforms and is in the standard C library:
#include <sys/stat.h>
bool FileExists(string filename) {
struct stat fileInfo;
return stat(filename.c_str(), &fileInfo) == 0;
}
If stat returns 0, the file (or directory) exists, otherwise it doesn't. I assume that you'll have to have access permissions on all directories in the file's path. I haven't tested portability, but this page suggests it shouldn't be an issue.

A better way:
std::ifstream stream;
stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
stream.open(fileName, std::ios::binary);

With C++17 you can use std::filesystem::exists.

Let's me give example with real running:
file does't exist:
file exist:
see http://www.cplusplus.com/reference/fstream/ifstream/ for more information about its public function.

Straight way without creating ifstream object.
if (!std::ifstream(filename))
{
// error! file doesn't exist.
}

Related

Stop ofstream from creating a file

I'm trying open a file and check if it exists yet it creates a new file if the given file does not exist. If it is going to automatically create a file, what's the point of the isOpen() then?
int main() {
std::ofstream defaultFile;
defaultFile.open("AAAAA.txt");
std::cout << defaultFile.is_open();//this will always print out "1"
}
what's the point of the isOpen() then?
Creating a file can fail for numerous reasons. One could be that you have no write access in the directory where you try to create the file. In that case
defaultFile.open("AAAAA.txt");
will fail and is_open will return false. If you want to know if the file exists before creating it you can do for example this:
ifstream f(name);
bool exits_and_can_be_opened = f.good();
Taken from here: https://stackoverflow.com/a/12774387/4117728, but note that since C++17 there is the Filesystem library with more straightforward ways to query properties of files.

Error in a C++(files and streams) program for creating a file

I have written this program in order to create a file using fstream and the output should show either the file has been created or not. I have run it on several online compilers like Codechef,C++ shell etc. The compilers has successfully compiled this program but the output is not coming accordingly, instead of saying file created compiler says error in creating file.
Can this be due to development tool?
Following is the code for this program:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("a.txt");
if(!file)
{
cout<<"Error in creating file!!!";
}
else
{
cout<<"File created successfully.";
file.close();
}
}
fstream.open() will fail if the file does not exist.
To create the file if it doesn't exist
file.open("a.txt", ios_base::out);
Or use ofstream
ofstream file;
file.open("a.txt");
The fstream constructor and open function open for read/write by default. The file must already exist to be opened in this mode. Instead, open for write:
file.open("a.txt", ios::out);
Your program's behavior is probably depending upon the operating system. BTW, if you want to learn more about them, read Operating Systems: Three Easy Pieces. Perhaps the current working directory already contains the file to be written or does not have the appropriate permissions (it should be writable to enable file creation). Details are operating system (and perhaps file system) specific. IIRC, some OSes (Windows probably) disallow opening a file which is already opened by some other process.
On Linux, you could use strace(1) to find out what system calls have failed (actually, it tells you all the system calls that have been executed by some given program or process).
This is [probably] not always guaranteed by C++ standards (but see sync_with_stdio), but many C++ standard libraries are above (and compatible with) the C standard library which sets errno(3) (see also strerror(3) and perror(3) ...) on failure; then you might try:
fstream file;
file.open("a.txt", ios::out);
if (!file) {
// perror("a.txt");
cout<<"Error in creating file!!!" << strerror(errno) << endl;
}
Of course, as other answers told you (this & that) you need the correct mode for open...
See also std::system_error

Data isn't being saved in the text file (C++ Fstream library )

I've been trying to save the score of the player in the game in a text file, but it doesn't do so.
This is the code I'm using:
//some code above
std::fstream TextScore ("Ranking.txt");
// some code above
if (Player->getFinal(Map) == true)
{
TextScore.open("Ranking.txt", ios::out);
TextScore << Player->getPoints();
TextScore.close();
//some code below
}
Then I check the text file and nothing has been saved, the file is empty.
I would like to know what I'm missing or doing wrong.
Thanks in advance.
std::fstream TextScore ("Ranking.txt");
This opens the file, as if TextScore.open("Ranking.txt"), std::ios::in|std::ios::out) was called.
TextScore.open("Ranking.txt", std::ios::out);
This opens it again.
The combination is not going to work if the file already exists. The first open will succeed and the second one will fail. After that, all I/O operations will fail. Open it just once, either in the constructor or in a separate open call. The most idiomatic C++ way would be
{
std::fstream TextScore ("Ranking.txt", std::ios::out);
TextScore << Player->getPoints();
}
No need to close the file explicitly thanks to RAII.
Opening the same file twice is certainly going to cause problems. Move the definition of TextScore into the body of the if statement in place of the call to TextScore.open(). And then you can remove the call to TextScore.close(); the destructor will close the file.

c++ overwrite already opened file

I am opening a file with ifstream to check if it exists. Then I close it and open it with ofstream to write to it, and I think setting ios::trunc flag allows me to overwrite it.
However I'd like the ability to keep the file open if it exists, but I used an ifstream to open it so does that mean I can't write to the file till I close and re-open using fstream or ofstream? I didn't use fstream to begin with because that wouldn't tell me if the file was already there or not.
Just open a read-write fstream on the file. You can test if the file previously existed (and was non-empty) by seeking to the end and seeing if you're at a non-zero offset. If so, the file existed, and you can do whatever with it. If not, the file didn't exist or was empty. Assuming you don't need to distinguish between those two cases, you can then proceed as if it did not exist.
For example:
// Error checking omitted for expository purposes
std::fstream f("file.txt", std::ios::in | std::ios::out);
f.seekg(0, std::ios::end)
bool didFileExist = (f.tellg() > 0);
f.seekg(0, std::ios::beg);
// Now use the file in read-write mode. If didFileExist is true, then the
// file previously existed (and has not yet been modified)
The setting ios::trunc erases previous contents of the file.
Try opening the file without this setting; with only the 'write' setting.
this is touching very serios problem - race conditions - what if somebody manages to do something with this file between closing and reopening? unfortunately iostream does not provide any means of resolving that issue - you can use cstdio FILE. If you want to turncate file if exists or create new one if not use fopen(name, "w"). If you want to turncate file if it exists or fail otherwise, then it seems standard library has nothing to offer, and you should go to other libraries or platform specific functions like OpenFile in windows.h

Failing to read file loaded with ifstream

void bot_manager_item::create_games()
{
games.clear();
std::ifstream paths_in("C:\\Users\\bill hank\\Documents\\bot_plugins\\directory_listing.txt", std::ios::in);
while (paths_in.good())
{
send_message("The path was good.");
char q[5000];
paths_in.getline(q, 5000);
send_message(q);
games.push_back(qanda(q));
}
paths_in.close();
}
The file I'm loading exists, what else might be wrong? paths_in.good keeps failing.
Edit: I figured it out. Wow am I annoyed by the answer to this. Basically Windows lets you say whether you want to show file extensions or not. This windows installation is set to say that the extension shouldn't be shown. So when I'm checking the file again and again I'm seeing: directory.txt and thinking that this means that everything is fine with the directory when in reality the filename was directory.txt.txt
If paths_in.good() keeps failing then it means that some of the stream error flags are set (badbit, eofbit or failbit).
eofbit - end of file was reached
badbit - error with the stream buffer such as memory shortage or an exception inside the stream buffer is cast
failbit - some other error beside eof was reached
In order to find out what happened, you need to check which errorbit is set first, and then find out more about the specific error, and what can cause it.
Out of curiosity, does this code output the contents of the file correctly? If this code works, then the problem is something else. If this code doesn't work, then that likely means that the file either isn't where you specified, or you don't have read permissions on it.
void bot_manager_item::create_games() {
std::ifstream paths_in("C:\\Users\\bill hank\\Documents\\bot_plugins\\directory_listing.txt");
char q[5000];
while (paths_in.getline(q, 5000)) {
std::cout << q << std::endl;
}
}
This code does a few minor things differently.
std::ios::in doesn't need to be explicitly specified for std::ifstream.
it doesn't use is_good, while that should be fine, you can just treat the std::ifstream as a bool which will be true when it is in a good state.
getline() returns a reference to the stream it operated on, so you can just put that whole line in the condition.
cosmetic, but no need to explicitly close the ifstream if it is about to go out of scope.