67

I've got a fstream my_file("test.txt"), but I don't know if test.txt exists. In case it exists, I would like to know if I can read it, too. How to do that?

I use Linux.

0

8 Answers 8

90

I would probably go with:

ifstream my_file("test.txt");
if (my_file.good())
{
  // read away
}

The good method checks if the stream is ready to be read from.

Sign up to request clarification or add additional context in comments.

3 Comments

This way you not only check if it exists & is readable, you actually open it.
Yeah, that's true. I read the OP's question that the file was already opened anyway, but I could be wrong.
Moreover, it cannot tell whether the file couldn't be opened because it didn't exist or because of access permission problems.
22

You might use Boost.Filesystem. It has a boost::filesystem::exist function.

I don't know how about checking read access rights. You could look in Boost.Filesystem too. However likely there will be no other (portable) way than try to actually read the file.

EDIT (2021-08-26): C++17 introduced <filesystem> and there you have std::filesystem::exists. Boost is no longer needed for this.

3 Comments

Does boost filesystem handle very long paths on windows (> 256)? We recently ran into the problem that the non unicode windows API has a maximum of 256 characters.
I don't know. You might check in documentation (at the link in my answer) but I'm not sure whether you will find it and its long. You might also ask on Boost news group. Another way is to simply check it.
@Richard Corden I checked very long paths with function boost::filesystem::create_directories. ANSI version (for char) threw an exception if given to long path (but the limit was somehow reached around 250 rather then MAX_PATH which is equal to 260). UNICODE version (for wchar_t) created as much folders as ANSI version would without throwing and returned successfully so not only it did not do the job but also it did not report the error. I don't know how is it with other functions but I suspect now they might behave badly as well.
12

C++17, cross-platform: Check file existence with std::filesystem::exists and readability with std::filesystem::status & std::filesystem::perms:

#include <iostream>
#include <filesystem> // C++17
namespace fs = std::filesystem;

/*! \return True if owner, group and others have read permission,
            i.e. at least 0444.
*/
bool IsReadable(const fs::path& p)
{
    std::error_code ec; // For noexcept overload usage.
    auto perms = fs::status(p, ec).permissions();
    if ((perms & fs::perms::owner_read) != fs::perms::none &&
        (perms & fs::perms::group_read) != fs::perms::none &&
        (perms & fs::perms::others_read) != fs::perms::none
        )
    {
        return true;
    }
    return false;
}

int main()
{
    fs::path filePath("path/to/test.txt");
    std::error_code ec; // For noexcept overload usage.
    if (fs::exists(filePath, ec) && !ec)
    {
        if (IsReadable(filePath))
        {
            std::cout << filePath << " exists and is readable.";
        }
    }
}

Consider also checking for the file type.

2 Comments

Great answer, but quick question: How can we check if this executable has permissions to read the file, rather than who has permissions to read the file?
You mention this is cross-platform. How are things like owner_read/grou_read and others_read resolved in Windows, where this isn't how permissions are structured?
11

if you are on unix then access() can tell you if it's readable. However if ACL's are in use, then it gets more complicated, in this case it's best to just open the file with ifstream and try read.. if you cannot read then the ACL may prohibit reading.

1 Comment

access() is a great way to introduce time-of-check-to-time-of-use bugs.
10

What Operating System/platform?

On Linux/Unix/MacOSX, you can use fstat.

On Windows, you can use GetFileAttributes.

Usually, there is no portable way of doing this with standard C/C++ IO functions.

6 Comments

Why do you say that, you could always just try to open a file with fopen and if it returns 0 you can deduce portably that the file is nonexistent.
fstat is available on windows, too, in sys/stat.h.
@Blindy or it does exist, but you don't have permissions to access it. What then? :q Your deduction is wrong.
@sasq makes no difference, the title literally says "and is readable". A file you don't have permission to access is by definition non-readable. Critical thinking will get you far in life!
@Blindy I was refering to your comment, not to the title or original post. My point was that opening a file just to check if it exists may have side effects that one does not necessarily desire, including a possibility to accidentally damage the file (e.g. if one opens it for writing as well and it happens that it exists). And spare me the "critical thinking" ad personam.
|
6

Since C++11 it's possible to use implicit operator bool instead of good():

ifstream my_file("test.txt");
if (my_file) {
  // read away
}

Comments

2

I know the poster eventually said they were using Linux, but I'm kind of surprised that no one mentioned the PathFileExists() API call for Windows.

You will need to include the Shlwapi.lib library, and Shlwapi.h header file.

#pragma comment(lib, "shlwapi.lib")
#include <shlwapi.h>

the function returns a BOOL value and can be called like so:

if( PathFileExists("C:\\path\\to\\your\\file.ext") )
{
    // do something
}

1 Comment

I ran across claims that PathFileExists() is unreliable: mfctips.com/tag/file-exists
0

Concerning the use of fstat in windows, I am not sure if it is what you want. From Microsoft the file must be already open. Stat should work for you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.