I'm working on TreeView for directories and files. Users can select a file or directory and then operate on it. This requires me to have a way to perform different actions according to the user's choice.
Currently, I am doing the following to determine whether the path is a file or a directory:
bool bIsFile = false; bool bIsDirectory = false; try { string[] subfolders = Directory.GetDirectories(strFilePath); bIsDirectory = true; bIsFile = false; } catch(System.IO.IOException) { bIsFolder = false; bIsFile = true; }
I can't help feeling that there is a better way to do it! I hope to find a standard. NET method to deal with this problem, but I haven't been able to. Is there such a method? If not, what is the most direct way to determine whether the path is a file or a directory?
#1 building
This is what we use:
using System; using System.IO; namespace crmachine.CommonClasses { public static class CRMPath { public static bool IsDirectory(string path) { if (path == null) { throw new ArgumentNullException("path"); } string reason; if (!IsValidPathString(path, out reason)) { throw new ArgumentException(reason); } if (!(Directory.Exists(path) || File.Exists(path))) { throw new InvalidOperationException(string.Format("Could not find a part of the path '{0}'",path)); } return (new System.IO.FileInfo(path).Attributes & FileAttributes.Directory) == FileAttributes.Directory; } public static bool IsValidPathString(string pathStringToTest, out string reasonForError) { reasonForError = ""; if (string.IsNullOrWhiteSpace(pathStringToTest)) { reasonForError = "Path is Null or Whitespace."; return false; } if (pathStringToTest.Length > CRMConst.MAXPATH) // MAXPATH == 260 { reasonForError = "Length of path exceeds MAXPATH."; return false; } if (PathContainsInvalidCharacters(pathStringToTest)) { reasonForError = "Path contains invalid path characters."; return false; } if (pathStringToTest == ":") { reasonForError = "Path consists of only a volume designator."; return false; } if (pathStringToTest[0] == ':') { reasonForError = "Path begins with a volume designator."; return false; } if (pathStringToTest.Contains(":") && pathStringToTest.IndexOf(':') != 1) { reasonForError = "Path contains a volume designator that is not part of a drive label."; return false; } return true; } public static bool PathContainsInvalidCharacters(string path) { if (path == null) { throw new ArgumentNullException("path"); } bool containedInvalidCharacters = false; for (int i = 0; i < path.Length; i++) { int n = path[i]; if ( (n == 0x22) || // " (n == 0x3c) || // < (n == 0x3e) || // > (n == 0x7c) || // | (n < 0x20) // the control characters ) { containedInvalidCharacters = true; } } return containedInvalidCharacters; } public static bool FilenameContainsInvalidCharacters(string filename) { if (filename == null) { throw new ArgumentNullException("filename"); } bool containedInvalidCharacters = false; for (int i = 0; i < filename.Length; i++) { int n = filename[i]; if ( (n == 0x22) || // " (n == 0x3c) || // < (n == 0x3e) || // > (n == 0x7c) || // | (n == 0x3a) || // : (n == 0x2a) || // * (n == 0x3f) || // ? (n == 0x5c) || // \ (n == 0x2f) || // / (n < 0x20) // the control characters ) { containedInvalidCharacters = true; } } return containedInvalidCharacters; } } }
#2 building
I ran into this problem when I encountered a similar problem, but when a file or folder may not actually exist, I need to check whether the path of the file or folder exists. With regard to the above answers, some comments mentioned that they did not apply to this situation. I found a solution that seemed good to me (I use VB.NET, but can convert as needed):
Dim path As String = "myFakeFolder\ThisDoesNotExist\" Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "") 'returns True Dim path As String = "myFakeFolder\ThisDoesNotExist\File.jpg" Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "") 'returns False
I hope it helps someone!
#3 building
How to use these?
File.Exists(); Directory.Exists();
#4 building
from How to determine whether the path is a file or a directory :
// get the file attributes for file or directory FileAttributes attr = File.GetAttributes(@"c:\Temp"); //detect whether its a directory or file if ((attr & FileAttributes.Directory) == FileAttributes.Directory) MessageBox.Show("Its a directory"); else MessageBox.Show("Its a file");
. NET 4.0 + update
According to the following comments, if you are using. NET 4.0 or later (and the highest performance is not critical), you can write code in a more concise way:
// get the file attributes for file or directory FileAttributes attr = File.GetAttributes(@"c:\Temp"); if (attr.HasFlag(FileAttributes.Directory)) MessageBox.Show("Its a directory"); else MessageBox.Show("Its a file");
#5 building
The most accurate way is to use some interoperation code in shlwapi.dll
[DllImport(SHLWAPI, CharSet = CharSet.Unicode)] [return: MarshalAsAttribute(UnmanagedType.Bool)] [ResourceExposure(ResourceScope.None)] internal static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);
You can then call it this:
#region IsDirectory /// <summary> /// Verifies that a path is a valid directory. /// </summary> /// <param name="path">The path to verify.</param> /// <returns><see langword="true"/> if the path is a valid directory; /// otherwise, <see langword="false"/>.</returns> /// <exception cref="T:System.ArgumentNullException"> /// <para><paramref name="path"/> is <see langword="null"/>.</para> /// </exception> /// <exception cref="T:System.ArgumentException"> /// <para><paramref name="path"/> is <see cref="F:System.String.Empty">String.Empty</see>.</para> /// </exception> public static bool IsDirectory(string path) { return PathIsDirectory(path); }