更好的方法来检查路径是文件还是目录?

我正在处理目录和文件的TreeView。用户可以选择一个文件或目录,然后对其进行操作。这要求我有一个方法,根据用户的选择执行不同的操作。

目前,我正在做这样的事情,以确定路径是文件还是目录:

bool bIsFile = false;
bool bIsDirectory = false;


try
{
string[] subfolders = Directory.GetDirectories(strFilePath);


bIsDirectory = true;
bIsFile = false;
}
catch(System.IO.IOException)
{
bIsFolder = false;
bIsFile = true;
}

我不禁觉得有更好的方法可以做到这一点!我希望找到一个标准的。net方法来处理这个问题,但我还没有能够这样做。是否存在这样的方法,如果不存在,确定路径是文件还是目录的最直接的方法是什么?

348204 次浏览

用这些怎么样?

File.Exists();
Directory.Exists();

如何判断路径是文件还是目录:

// 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+

根据下面的评论,如果你使用的是。net 4.0或更高版本(最大性能不是关键),你可以用更简洁的方式编写代码:

// 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");

最准确的方法是使用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);

然后你可以这样调用它:

#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);
}

作为directory . exists()的替代方法,你可以使用file . getattributes()方法来获取文件或目录的属性,所以你可以创建一个像这样的helper方法:

private static bool IsDirectory(string path)
{
System.IO.FileAttributes fa = System.IO.File.GetAttributes(path);
return (fa & FileAttributes.Directory) != 0;
}

在填充包含该项的附加元数据的控件时,还可以考虑向TreeView控件的tag属性添加对象。例如,您可以为文件添加FileInfo对象,为目录添加DirectoryInfo对象,然后在tag属性中测试项目类型,以避免在单击项目时进行额外的系统调用以获取数据。

我使用以下,它还测试扩展,这意味着它可以用于测试,如果提供的路径是一个文件,但一个文件不存在。

private static bool isDirectory(string path)
{
bool result = true;
System.IO.FileInfo fileTest = new System.IO.FileInfo(path);
if (fileTest.Exists == true)
{
result = false;
}
else
{
if (fileTest.Extension != "")
{
result = false;
}
}
return result;
}

下面是我们使用的:

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;
}


}


}

当我遇到类似的问题时,我遇到了这个问题,除了我需要检查一个路径是否为文件或文件夹当该文件或文件夹可能实际上不存在时。上面有一些关于答案的评论,提到它们不适用于这种情况。我找到了一个解决方案(我使用VB。NET,但你可以转换,如果你需要),这似乎很适合我:

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

希望这能对别人有所帮助!

如果你想找到目录,包括那些标记为“hidden”和“system”的目录,试试这个(需要。net V4):

FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory))

这是我所能想到的最好的Exists和Attributes属性的行为:

using System.IO;


public static class FileSystemInfoExtensions
{
/// <summary>
/// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
/// </summary>
/// <param name="fileSystemInfo"></param>
/// <returns></returns>
public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
{
if (fileSystemInfo == null)
{
return false;
}


if ((int)fileSystemInfo.Attributes != -1)
{
// if attributes are initialized check the directory flag
return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
}


// If we get here the file probably doesn't exist yet.  The best we can do is
// try to judge intent.  Because directories can have extensions and files
// can lack them, we can't rely on filename.
//
// We can reasonably assume that if the path doesn't exist yet and
// FileSystemInfo is a DirectoryInfo, a directory is intended.  FileInfo can
// make a directory, but it would be a bizarre code path.


return fileSystemInfo is DirectoryInfo;
}
}

下面是测试结果:

    [TestMethod]
public void IsDirectoryTest()
{
// non-existing file, FileAttributes not conclusive, rely on type of FileSystemInfo
const string nonExistentFile = @"C:\TotallyFakeFile.exe";


var nonExistentFileDirectoryInfo = new DirectoryInfo(nonExistentFile);
Assert.IsTrue(nonExistentFileDirectoryInfo.IsDirectory());


var nonExistentFileFileInfo = new FileInfo(nonExistentFile);
Assert.IsFalse(nonExistentFileFileInfo.IsDirectory());


// non-existing directory, FileAttributes not conclusive, rely on type of FileSystemInfo
const string nonExistentDirectory = @"C:\FakeDirectory";


var nonExistentDirectoryInfo = new DirectoryInfo(nonExistentDirectory);
Assert.IsTrue(nonExistentDirectoryInfo.IsDirectory());


var nonExistentFileInfo = new FileInfo(nonExistentDirectory);
Assert.IsFalse(nonExistentFileInfo.IsDirectory());


// Existing, rely on FileAttributes
const string existingDirectory = @"C:\Windows";


var existingDirectoryInfo = new DirectoryInfo(existingDirectory);
Assert.IsTrue(existingDirectoryInfo.IsDirectory());


var existingDirectoryFileInfo = new FileInfo(existingDirectory);
Assert.IsTrue(existingDirectoryFileInfo.IsDirectory());


// Existing, rely on FileAttributes
const string existingFile = @"C:\Windows\notepad.exe";


var existingFileDirectoryInfo = new DirectoryInfo(existingFile);
Assert.IsFalse(existingFileDirectoryInfo.IsDirectory());


var existingFileFileInfo = new FileInfo(existingFile);
Assert.IsFalse(existingFileFileInfo.IsDirectory());
}

如果路径是目录或文件,只需要这一行即可:

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)

这是我的:

    bool IsPathDirectory(string path)
{
if (path == null) throw new ArgumentNullException("path");
path = path.Trim();


if (Directory.Exists(path))
return true;


if (File.Exists(path))
return false;


// neither file nor directory exists. guess intention


// if has trailing slash then it's a directory
if (new[] {"\\", "/"}.Any(x => path.EndsWith(x)))
return true; // ends with slash


// if has extension then its a file; directory otherwise
return string.IsNullOrWhiteSpace(Path.GetExtension(path));
}

这与别人的答案相似,但并不完全相同。

using System;
using System.IO;
namespace FileOrDirectory
{
class Program
{
public static string FileOrDirectory(string path)
{
if (File.Exists(path))
return "File";
if (Directory.Exists(path))
return "Directory";
return "Path Not Exists";
}
static void Main()
{
Console.WriteLine("Enter The Path:");
string path = Console.ReadLine();
Console.WriteLine(FileOrDirectory(path));
}
}
}

我知道这游戏太迟了,但我还是想分享这个。如果你只是将路径作为字符串来处理,这很容易:

private bool IsFolder(string ThePath)
{
string BS = Path.DirectorySeparatorChar.ToString();
return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}
例如< p >: ThePath == "C:\SomeFolder\File1.txt"将结束为:

return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)
< p >另一个例子: ThePath == "C:\SomeFolder\"将结束为:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)
如果没有后面的反斜杠,也可以正常工作: ThePath == "C:\SomeFolder"将结束为:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

请记住,这只适用于路径本身,而不适用于路径和“物理磁盘”之间的关系……所以它不能告诉你路径/文件是否存在或类似的东西,但它肯定能告诉你路径是文件夹还是文件……

我需要这个,posts帮助它,这让它变成一行,如果路径根本不是路径,它就会返回并退出方法。它解决了上述所有问题,也不需要后面的斜杠。

if (!Directory.Exists(@"C:\folderName")) return;

使用这篇文章中选择的答案,我看了评论,并给予信任 @ŞafakGür, @Anthony和@Quinn Wilson的信息位,让我得到了这个改进的答案,我写了并测试:

    /// <summary>
/// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool? IsDirFile(this string path)
{
bool? result = null;


if(Directory.Exists(path) || File.Exists(path))
{
// get the file attributes for file or directory
var fileAttr = File.GetAttributes(path);


if (fileAttr.HasFlag(FileAttributes.Directory))
result = true;
else
result = false;
}


return result;
}

这样不行吗?

var isFile = Regex.IsMatch(path, @"\w{1,}\.\w{1,}$");

在结合其他答案的建议后,我意识到我得到了与罗尼·奥弗比的回答是相同的东西。以下是一些测试,指出一些需要考虑的问题:

  1. 文件夹可以有“扩展名”:C:\Temp\folder_with.dot
  2. 文件不能以目录分隔符(斜杠)结束
  3. 从技术上讲,有两个特定于平台的目录分隔符——即也可能不会可以是斜杠(Path.DirectorySeparatorCharPath.AltDirectorySeparatorChar)

测试(Linqpad)

var paths = new[] {
// exists
@"C:\Temp\dir_test\folder_is_a_dir",
@"C:\Temp\dir_test\is_a_dir_trailing_slash\",
@"C:\Temp\dir_test\existing_folder_with.ext",
@"C:\Temp\dir_test\file_thats_not_a_dir",
@"C:\Temp\dir_test\notadir.txt",
// doesn't exist
@"C:\Temp\dir_test\dne_folder_is_a_dir",
@"C:\Temp\dir_test\dne_folder_trailing_slash\",
@"C:\Temp\dir_test\non_existing_folder_with.ext",
@"C:\Temp\dir_test\dne_file_thats_not_a_dir",
@"C:\Temp\dir_test\dne_notadir.txt",
};


foreach(var path in paths) {
IsFolder(path/*, false*/).Dump(path);
}

结果

C:\Temp\dir_test\folder_is_a_dir
True
C:\Temp\dir_test\is_a_dir_trailing_slash\
True
C:\Temp\dir_test\existing_folder_with.ext
True
C:\Temp\dir_test\file_thats_not_a_dir
False
C:\Temp\dir_test\notadir.txt
False
C:\Temp\dir_test\dne_folder_is_a_dir
True
C:\Temp\dir_test\dne_folder_trailing_slash\
True
C:\Temp\dir_test\non_existing_folder_with.ext
False (this is the weird one)
C:\Temp\dir_test\dne_file_thats_not_a_dir
True
C:\Temp\dir_test\dne_notadir.txt
False

方法

/// <summary>
/// Whether the <paramref name="path"/> is a folder (existing or not);
/// optionally assume that if it doesn't "look like" a file then it's a directory.
/// </summary>
/// <param name="path">Path to check</param>
/// <param name="assumeDneLookAlike">If the <paramref name="path"/> doesn't exist, does it at least look like a directory name?  As in, it doesn't look like a file.</param>
/// <returns><c>True</c> if a folder/directory, <c>false</c> if not.</returns>
public static bool IsFolder(string path, bool assumeDneLookAlike = true)
{
// https://stackoverflow.com/questions/1395205/better-way-to-check-if-path-is-a-file-or-a-directory
// turns out to be about the same as https://stackoverflow.com/a/19596821/1037948


// check in order of verisimilitude


// exists or ends with a directory separator -- files cannot end with directory separator, right?
if (Directory.Exists(path)
// use system values rather than assume slashes
|| path.EndsWith("" + Path.DirectorySeparatorChar)
|| path.EndsWith("" + Path.AltDirectorySeparatorChar))
return true;


// if we know for sure that it's an actual file...
if (File.Exists(path))
return false;


// if it has an extension it should be a file, so vice versa
// although technically directories can have extensions...
if (!Path.HasExtension(path) && assumeDneLookAlike)
return true;


// only works for existing files, kinda redundant with `.Exists` above
//if( File.GetAttributes(path).HasFlag(FileAttributes.Directory) ) ...;


// no idea -- could return an 'indeterminate' value (nullable bool)
// or assume that if we don't know then it's not a folder
return false;
}

也许是UWP c#

public static async Task<IStorageItem> AsIStorageItemAsync(this string iStorageItemPath)
{
if (string.IsNullOrEmpty(iStorageItemPath)) return null;
IStorageItem storageItem = null;
try
{
storageItem = await StorageFolder.GetFolderFromPathAsync(iStorageItemPath);
if (storageItem != null) return storageItem;
} catch { }
try
{
storageItem = await StorageFile.GetFileFromPathAsync(iStorageItemPath);
if (storageItem != null) return storageItem;
} catch { }
return storageItem;
}
我明白了,我迟到了10年。 我面临的情况是,从某些属性中,我可以接收文件名或完整的文件路径。如果没有提供路径,我必须通过附加一个由另一个属性提供的“全局”目录路径来检查文件是否存在

对我来说

var isFileName = System.IO.Path.GetFileName (str) == str;

成功了。 好吧,这不是魔法,但也许这可以为某人节省几分钟的思考时间。 因为这只是一个字符串解析,所以带点的diri -names可能会给出假阳性…< / p >

这里的派对很晚了,但我发现Nullable<Boolean>返回值相当难看——IsDirectory(string path)返回null并不等同于没有详细注释的不存在的路径,所以我想出了以下方法:

public static class PathHelper
{
/// <summary>
/// Determines whether the given path refers to an existing file or directory on disk.
/// </summary>
/// <param name="path">The path to test.</param>
/// <param name="isDirectory">When this method returns, contains true if the path was found to be an existing directory, false in all other scenarios.</param>
/// <returns>true if the path exists; otherwise, false.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="path"/> is null.</exception>
/// <exception cref="ArgumentException">If <paramref name="path"/> equals <see cref="string.Empty"/></exception>
public static bool PathExists(string path, out bool isDirectory)
{
if (path == null) throw new ArgumentNullException(nameof(path));
if (path == string.Empty) throw new ArgumentException("Value cannot be empty.", nameof(path));


isDirectory = Directory.Exists(path);


return isDirectory || File.Exists(path);
}
}

这个helper方法写得足够冗长和简洁,以便在第一次阅读时就能理解其意图。

/// <summary>
/// Example usage of <see cref="PathExists(string, out bool)"/>
/// </summary>
public static void Usage()
{
const string path = @"C:\dev";


if (!PathHelper.PathExists(path, out var isDirectory))
return;


if (isDirectory)
{
// Do something with your directory
}
else
{
// Do something with your file
}
}

只需添加一个边缘框-“文件夹选择”;在路径

在我的应用程序中,我得到了传递给我的最近打开的路径,其中一些有“文件夹选择”。最后。

一些fileopendialog和WinMerge添加“文件夹选择”;到路径(这是真的)。

显示

但是在Windows操作系统下“文件夹选择”;不是一个建议的文件或文件夹名称(如don't do it, ever - 摇动的拳头)。 如上所述:http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx

不要以空格或句号结束文件或目录名。虽然底层文件系统可能支持这样的名称,但Windows shell和用户界面不支持。但是,将句点指定为名称的第一个字符是可以接受的。例如,“temp"”。

因此,“文件夹选择”;不应该被使用,它可以被。(太棒了)。

足够的解释-我的代码(我很喜欢枚举):

public static class Utility
{
public enum ePathType
{
ePathType_Unknown = 0,
ePathType_ExistingFile = 1,
ePathType_ExistingFolder = 2,
ePathType_ExistingFolder_FolderSelectionAdded = 3,
}


public static ePathType GetPathType(string path)
{
if (File.Exists(path) == true) { return ePathType.ePathType_ExistingFile; }
if (Directory.Exists(path) == true) { return ePathType.ePathType_ExistingFolder; }


if (path.EndsWith("Folder Selection.") == true)
{
// Test the path again without "Folder Selection."
path = path.Replace("\\Folder Selection.", "");
if (Directory.Exists(path) == true)
{
// Could return ePathType_ExistingFolder, but prefer to let the caller known their path has text to remove...
return ePathType.ePathType_ExistingFolder_FolderSelectionAdded;
}
}


return ePathType.ePathType_Unknown;
}
}
public bool IsDirectory(string path) {
return string.IsNullOrEmpty(Path.GetFileName(path)) || Directory.Exists(path);
}

检查路径文件名是否为空字符串,或者目录是否存在。这样就不会出现文件属性错误,同时仍然为可能存在的故障提供冗余。