I want to know how to check (in unmanaged Visual C++ code) if a string has a valid format to represent file path or folder path. The physical file or folder path itself may or may not exist in this case. To check correct string format is major goal in my case. I need to know if a string has a the right format to be a valid file path or it doesn't have? There are many posts about it for C# but no one for unmanaged C++. How to do it in unmanaged C++ in Visual C++?
-
In c++, you may try using [`regex`](http://en.cppreference.com/w/cpp/regex/basic_regex) to do this. – πάντα ῥεῖ Dec 21 '14 at 08:54
-
Any string is a valid path. What would be an example of something it should reject? – Barmar Dec 21 '14 at 09:01
-
For example: "C:\MainFolder\MyFolder\myTextFile.txt" or "MyFolder\myTextFile.txt" are absolute and relative paths accordingly. But "C:^^>\:_Wrong_path" is wrong path example. – user3769902 Dec 21 '14 at 09:13
-
http://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names Note you cannot check with 100% reliability, a filesystem can impose its own restrictions. – n. m. could be an AI Dec 21 '14 at 09:14
-
Just "try using it" (e.g. open the filename for reading, or if you intend to create, open for write). – Mats Petersson Dec 21 '14 at 09:33
-
@MatsPetersson this is not enough, directories in the path may or may not exist. – n. m. could be an AI Dec 21 '14 at 09:37
-
Right, so are you ONLY trying to find DISTINCTLY incorrect paths, or those that are superficially valid, but not really, such as `c:\foo\..\..\bar.txt`? Or `c:\foo\bar.txt` when `bar.txt` is a directory or `foo` is not a directory? As my answer states, this gets increasingly difficult the more you look at it, as there are a lot of cases that "could be OK, maybe not". What about files in non-ascii character sets (chines, japanese, etc)? – Mats Petersson Dec 21 '14 at 12:03
3 Answers
The ONLY 100% certain way is to "try it". You can write code to determine simple cases, but there are will always be wrinkles that you need to deal with, unless you ALSO find out what filesystem the drive is that the file lives on, which, since Windows allows "junctions", means parsing the entire path down to the final part.
It is much simpler to do :
std::ifstream test(proposedName);
if (!test)
{
std::cout << "The file doesn't exist" << std::endl;
}
If you really want to be fancy, you could take a look at errno
to figure out if it was "invalid filename" or "file doesn't exist". But in general, it's pointless to try to second guess the validity of a filename and path, since there are WAY too many rules that may or may not apply to YOUR particular case.
It gets more complicated if you have directories "halfway" that doesn't exist. You'd simply have to parse the path and try creating the directory on the way [and deleting it again if the whole process fails]. However, this is further complicated by the fact that you have to deal with non-canonical paths. Is c:\blah\..\.\foo\..\bar\xxx.9\..\..\bleurgh\papa.txt
a valid filename? To solve this you'd have to FIRST canonicalize the name.
PathCanonicalize
or it's friends would help with this. But it's still full of nasty complicated bits that are VERY hard to solve.
Sure, you can try writing a regex or something to catch the simple cases, but you will still end up with cases which are hard to figure out.
Note that there are situations when a path may appear valid, but isn't. Imagine that we have this path: c:\directory\foo\bar.txt
. Now, that looks perfectly valid, we may have to create c:\direoctry
and foo
inside this. But what if c:\directory\foo
is an already existing file? Would you remove the file and create a directory in its place? Or would you say it's "fine" and then fail when you try to create the directory? I don't know the answer, and this sort of complication is why I say "the only way to make sure is to try it" - everything else is just chasing your tail, or approximating the correctness.
And of course, it gets even more complicated if we take file permissions into account.
[And erenon makes a good point - even if you check it now, between the point you check something, and you actually start using your path, you may well have had changes to the directory structure making a previously valid name invalid - or vice versa - this sort of problem is often called "TOCTOU" - "Time of Check to Time of Use"]

- 126,704
- 14
- 140
- 227
-
Why is it necessary to canonicalize the filename to check if it compiles with the correct format? – Alan Dec 21 '14 at 10:36
-
Because it may be "invalid" due to incorrect "up one directory", e.g. 'c:\..\foo.txt' is invalid, but does not contain any invalid combinations... – Mats Petersson Dec 21 '14 at 11:17
-
Actually `PathCanonicalize` will, at least to some degree, also validate the name, and return `FALSE` if the name is not valid. I'm not convinced that this is sufficient to ensure "always good name", but it's a start. – Mats Petersson Dec 21 '14 at 11:20
-
1I would contend that 'C:\..\foo.txt' is valid as far as format is concerned, even though it may be invalid with regards to file existance. I read the question as "I have a string and the path syntax, but no file system to check against; does this string have correct syntax". – Alan Dec 21 '14 at 11:26
-
Right, so that depends on what you are trying to achieve. And yes, it may well be correct what you are saying, and that a check should accept this path. But it's still invalid on EVERY Windows file-system currently in existance. – Mats Petersson Dec 21 '14 at 11:40
-
And I think that's part of what I'm trying to say here - it gets INCREDIBLY HARD to validate everything. It's possible to check that the string is "seemingly valid", but it's hard to be sure that it's actually a useful path that is valid on a particular filesystem. – Mats Petersson Dec 21 '14 at 11:42
-
That's pretty much what I'm getting at too; checking the string conforms to the format (i.e.: is seemingly valid) is do-able, but requires considering lots of edge cases (COM ports, non-latin chars, etc.). Checking that the path is valid on a particular filesystem pretty much does require attempting to use it on said filesystem. – Alan Dec 21 '14 at 18:21
-
The proposed code checks, whether a file is **accessible**. This is not the same as being a legal resource locator. – IInspectable Mar 23 '15 at 13:42
-
And therein lies the problem. Because there are so many different rules, depending on what filesystem it is (it may be an old FAT-16 filesystem with "only short filenames", or it may be a path to a CDROM where new files can not be created). Without also doing a whole lot of extra code to figure out what those rules are - and it's entirely possible to make up your own rules if you write your own filesystem - files must always have even number of characters in the name for example. – Mats Petersson Mar 23 '15 at 20:58
If you incorporate a recent version of boost you can use FileSystem that does the job for you and takes care of all the usual problems (\ vs \\ etc...). It also provides some other facilities (filesize, permissions etc...)
#include <boost/filesystem.hpp>
string filePath= "C:\Temp\myExample.txt";
if (boost::filesystem::exists(filePath)) // does filePath actually exist?
cout<<"This is a valid file";
else
cout<<"The file does not exist";
Here is the link.
http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/tutorial.html
It should be in the official C++ at some point, full details here.
http://en.cppreference.com/w/cpp/experimental/fs
Hope that helps,

- 3,564
- 1
- 27
- 49
-
1`exists` is such an epic misnomer. No, the code doesn't check whether a file exists. It checks, whether a file is **accessible**, or at least queryable. Assume that the security token of the caller of your code does not grant access to *C:\Temp*. At that point your check fails, even though *myExample.txt* could very well be there. – IInspectable Mar 23 '15 at 13:45
-
do you know if std::filesystem::exists(filePath) is protected from code injections? is there way a user can enter a code/combination of symbols in a path input field, that will lead to malicious effects when parsed by the "exists" function? – OverInflatedWalrus Jun 01 '22 at 10:03
I think the answer of Mats Petersson describes the true answer. I'd like to point out a common error. Assume the following function:
bool fileExists(const char* fileName)
{
std::ifstream test(fileName);
return (test) ? true : false;
}
Then using it this way:
if (fileExists(myFile))
{
// assume myFile is a valid file
// WRONG!
}
There is a huge race condition here. myFile
might become invalid after checking but before using it. The only way to make sure it does exist is to open it and keep the file handle around.

- 18,838
- 2
- 61
- 93