109

In my application the user can enter a filename. Before processing I'd like to check if the input String is a valid filename on Windows Vista.

Whats the easiest way to do that?

By valid I'm reffering to legal and non-existing

8
  • When you say valid filename, are you referring to the fact that the file exists, or are you asking if the name would be allowed by the operation system? Commented Jan 10, 2011 at 19:09
  • 4
    Valid as in (a) existing, (b) legal, or (c) legal and non-existing? Commented Jan 10, 2011 at 19:09
  • 1
    Sry i should have clarified that. It should be (c) leagl and non-existing Commented Jan 10, 2011 at 19:09
  • 4
    @roflcopter: You must simply handle errors while creating the file. Any filesystem operation that involves an existence check is already potentially out-of-date by the time it returns, since the filesystem is a global shared resource. Commented Jan 10, 2011 at 19:15
  • 1
    @Roflcoptr: a file with the exact same name being created between the moment you check validity and/or existence, and the moment when you actually attempt to create it is not to be regarded normal program flow. You should verify that the file does not exist, but when you actually do create the file, that knowledge is already old and should be considered only an educated guess. It is likely to still be true, but it is not guaranteed. Commented Jan 10, 2011 at 19:20

7 Answers 7

152

Check whether filename.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 and !File.Exists(Path.Combine(someFolder, filename))

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

13 Comments

<quote>The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names.</quote> Also, that property is deprecated.
counter-example: "http://www.microsoft.com/" passes your test but is not a valid filename, ditto for "::::"
More counter-examples: " " is not valid and new String('x', 1024) is not valid either.
@shellster You can rename a file to ".txt" in windows explorer by telling explorer to rename the file to ".txt.". Just a tip (or ".txt........" will work too).
that should be < 0 instead of >= 0 as IndexOfAny() will return -1 if none are found
|
44

Check against GetInvalidFileNameChars():

var isValid = !string.IsNullOrEmpty(fileName) && fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 && !File.Exists(Path.Combine(sourceFolder, fileName)); 

4 Comments

counter-example: "http://www.microsoft.com/" passes your test but is not a valid filename, ditto for "::::"
@Ben Voigt: You are correct that :::: was incorrectly regarded as valid. I've corrected the answer to indicate < 0 instead of == 0.
Oh, I just noticed you're using GetInvalidFileNameChars, not GetInvalidPathChars like SLaks. As long as it's a test for the filename only and not a filename-with-path, that'll be ok.
@Ben Voigt: Since the OP asked about validating file names, and paths only implicitly to validate file non-existence, I used GetInvalidFileNameChars :-)
13

If the file is going to be created, You should use a file dialog to specify the directory path. There's a short list of illegal characters for file names.

The only truly reliable way to tell if a file name is acceptable is to try it. Permissions is a morass.

4 Comments

The file dialog is a red herring, but +1 for "only truly reliable way ... is to try it".
Agreed. Even if the filename doesn't exist and contains no illegal characters, there are a number of reasons why the file won't get created, the most obvious being a lack of create permission to the directory.
There are cases when you need to save to an unknown path, but you don't want the user to choose the exact path. In these cases, a file dialog is not viable.
the main reason to suggest a file dialog is to figure out what some valid path is. If you have that, it can be modified as needed.
3

If you create a DirectoryInfo for the file, it will throw an exception if there are any problems with the file/directory name, either invalid chars or length.

DirectoryInfo di = new DirectoryInfo(myFileName); Console.WriteLine("This filename/path could be valid. The folder might not exist yet though.") if(di.Exists) Console.WriteLine("This file already exist.") 

Not great that it is using exceptions for flow control, but you can be confident that it is right. OTOH, if you already planned to give the calling code an exception, mission accomplished.

2 Comments

This works for validating a file path, not a filename.
@41686d6564 True, so use FileInfo instead.
2

I use this:

public static bool IsValidFileName(string name) { if(string.IsNullOrWhiteSpace(name)) return false; if(name.Length > 1 && name[1] == ':') { if(name.Length < 4 || name.ToLower()[0] < 'a' || name.ToLower()[0] > 'z' || name[2] != '\\') return false; name = name.Substring(3); } if(name.StartsWith("\\\\")) name = name.Substring(1); if(name.EndsWith("\\") || !name.Trim().Equals(name) || name.Contains("\\\\") || name.IndexOfAny(Path.GetInvalidFileNameChars().Where(x=>x!='\\').ToArray()) >= 0) return false; return true; } 

Should take care of everything but reserved names, permissions, and length restrictions. This accepts both relative and absolute filenames.

Comments

1

This is just an idea. One should populate the exception list:

public static bool IsValidFilename(string filename) { try { File.OpenRead(filename).Close(); } catch (ArgumentException) { return false; } catch (Exception) { } return true; } 

2 Comments

What if the file doesn't exist yet?
@MikeCheel The code only returns false if an argument exception is thrown. That exception is only thrown is the filename is invalid.
1

For first part(Valid Filename), I use all ways and a temporary file creation to check if a file can be named as expected or throws an exception.
In some cases creating a file will not raise an exception until trying to delete it(eg: CON).
I also usa removePath arg to dictate it that file is just the name of file without its path.

using System.IO; using System.Text; 
private static readonly byte[] TestFileBytes = Encoding.ASCII.GetBytes(@"X"); 
public bool IsFileNameValid(string file, bool removePath = false) { try { if (string.IsNullOrEmpty(file)) return false; string fileNamePart = removePath ? Path.GetFileName(file) : file; if (fileNamePart.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) return false; string fileName = Path.Combine(Path.GetTempPath(), fileNamePart); using FileStream fileStream = File.Create(fileName); { fileStream.Write(TestFileBytes, 0, TestFileBytes.Length); } File.Delete(fileName); return true; } catch { return false; } } 

If there is any denial of access to temp folder use a custom folder for creating test file.

This method will result false for . or .. or ... r any sequence of dot-only names in Windows, and also you can't create them manually, but those are not actually invalid names! those are uncreatable names for file or something like that ;).

And for next part(Not exists) just use: !File.Exists(yourFileNameWithPath).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.