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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1395205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 16:02:58  来源:igfitidea点击:

Better way to check if a Path is a File or a Directory?

c#.netfilepathdirectory

提问by SnAzBaZ

I am processing a TreeViewof directories and files. A user can select either a file or a directory and then do something with it. This requires me to have a method which performs different actions based on the user's selection.

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

At the moment I am doing something like this 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 cannot help to feel that there is a better way to do this! I was hoping to find a standard .NET method to handle this, but I haven't been able to do so. Does such a method exist, and if not, what is the most straightforward means to determine whether a path is a file or directory?

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

采纳答案by Quinn Wilson

From How to tell if path is file or 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");

Update for .NET 4.0+

.NET 4.0+ 更新

Per the comments below, if you are on .NET 4.0 or later (and maximum performance is not critical) you can write the code in a cleaner way:

根据下面的评论,如果您使用 .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");

回答by llamaoo7

How about using these?

用这些怎么样?

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

回答by Scott Dorman

The most accurate approach is going to be using some interop code from the shlwapi.dll

最准确的方法是使用 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 would then call it like 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);
}

回答by Michael A. McCloskey

As an alternative to Directory.Exists(), you can use the File.GetAttributes() method to get the attributes of a file or a directory, so you could create a helper method like this:

作为 Directory.Exists() 的替代方法,您可以使用 File.GetAttributes() 方法来获取文件或目录的属性,因此您可以创建这样的辅助方法:

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

You could also consider adding an object to the tag property of the TreeView control when populating the control that contains additional metadata for the item. For instance, you could add a FileInfo object for files and a DirectoryInfo object for directories and then test for the item type in the tag property to save making additional system calls to get that data when clicking on the item.

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

回答by Stu1983

I use the following, it also tests the extension which means it can be used for testing if the path supplied is a file but a file that doesn't exist.

我使用以下内容,它还测试扩展名,这意味着它可以用于测试提供的路径是否是文件但不存在的文件。

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

回答by PMBottas

Here's 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;
    }

  }

}

回答by lhan

I came across this when facing a similar problem, except I needed to check if a path is for a file or folder when that file or folder may not actually exist. There were a few comments on answers above that mentioned they would not work for this scenario. I found a solution (I use VB.NET, but you can convert if you need) that seems to work well for me:

我在遇到类似问题时遇到了这个问题,除了当该文件或文件夹可能实际上不存在时,我需要检查该文件或文件夹的路径是否存在。上面有一些关于答案的评论,提到它们不适用于这种情况。我找到了一个似乎对我很有效的解决方案(我使用 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

Hopefully this can be helpful to someone!

希望这可以对某人有所帮助!

回答by jamie

If you want to find directories, including those that are marked "hidden" and "system", try this (requires .NET V4):

如果要查找目录,包括标记为“隐藏”和“系统”的目录,请尝试以下操作(需要 .NET V4):

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

回答by HAL9000

This was the best I could come up with given the behavior of the Exists and Attributes properties:

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

Here's how it tests out:

以下是它的测试方式:

    [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());
    }

回答by Gerard Gilabert Canal

With only this line you can get if a path is a directory or a file:

如果路径是目录或文件,则仅使用此行即可获得:

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