[c#] Лучший способ проверить, является ли Путь файлом или каталогом?



Answers

Как насчет их использования?

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

Я обрабатываю 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, чтобы справиться с этим, но я не смог этого сделать. Существует ли такой метод, а если нет, то что является самым простым способом определить, является ли путь файлом или каталогом?




Самый точный подход будет заключаться в использовании некоторого кода взаимодействия из файла 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);
}



Вот мой:

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

  }

}



Используя выбранный ответ на этом посту, я просмотрел комментарии и дал понять @ Ş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;
    }



Если вы хотите найти каталоги, в том числе те, которые отмечены как «скрытые» и «системные», попробуйте это (требуется .NET V4):

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



soooo в конце игры, которую я знаю, но думал, что я все равно поделюсь этим. Если вы работаете исключительно с путями как струны, то это легко понять как пирог:

private bool IsFolder(string ThePath)
{
    string BS = Path.DirectorySeparatorChar.ToString();
    return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}

например: ThePath == "C:\SomeFolder\File1.txt" в конечном итоге будет следующим:

return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)

Другой пример: ThePath == "C:\SomeFolder\" в конечном итоге будет следующим:

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

И это также будет работать без обратной обратной косой черты: ThePath == "C:\SomeFolder" в конечном итоге будет следующим:

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

Имейте в виду, что это работает только с самими путями, а не с отношением между контуром и «физическим диском» ... поэтому он не может сказать вам, существует ли путь / файл или что-то в этом роде, но он уверен может сказать вам, является ли путь папкой или файлом ...




Это использует DirectoryInfo для получения атрибута

Dim newnode As TreeNode
Dim dirs As New DirectoryInfo(node.FullPath)
For Each dir As DirectoryInfo In dirs.GetDirectories()
    If dir.Attributes = FileAttributes.Directory Then

    Else

    End If
Next

Это будет работать, если вы попытаетесь пройти через DirectoryInfo, пытаясь создать TreeView или прочитать TreeView




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



Links