Betere manier om te controleren of een pad een bestand of een map is?

Ik ben een TreeViewvan mappen en bestanden aan het verwerken. Een gebruiker kan een bestand of een map selecteren en er vervolgens iets mee doen. Dit vereist dat ik een methode heb die verschillende acties uitvoert op basis van de selectie van de gebruiker.

Op dit moment doe ik zoiets om te bepalen of het pad een bestand of een map is:

bool bIsFile = false;
bool bIsDirectory = false;
try
{
    string[] subfolders = Directory.GetDirectories(strFilePath);
    bIsDirectory = true;
    bIsFile = false;
}
catch(System.IO.IOException)
{
    bIsFolder = false;
    bIsFile = true;
}

Ik heb het gevoel dat er een betere manier is om dit te doen! Ik hoopte een standaard .NET-methode te vinden om dit aan te pakken, maar het is me niet gelukt. Bestaat zo’n methode, en zo niet, wat is de meest eenvoudige manier om te bepalen of een pad een bestand of een map is?


Antwoord 1, autoriteit 100%

Van Hoe weet ik of een pad is bestand of map:

// 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 voor .NET 4.0+

Volgens de onderstaande opmerkingen kunt u de code op een schonere manier schrijven als u .NET 4.0 of hoger gebruikt (en maximale prestaties niet essentieel zijn):

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

Antwoord 2, autoriteit 42%

Wat dacht je van deze te gebruiken?

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

Antwoord 3, autoriteit 3%

Met alleen deze regel kun je zien of een pad een map of een bestand is:

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

Antwoord 4, autoriteit 2%

Dit is de mijne:

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

Het lijkt op de antwoorden van anderen, maar is niet precies hetzelfde.


Antwoord 5

Als alternatief voor Directory.Exists(), kunt u de methode File.GetAttributes() gebruiken om de kenmerken van een bestand of een map op te halen, dus u kunt een hulpmethode als deze maken:

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

U kunt ook overwegen een object toe te voegen aan de tag-eigenschap van het TreeView-besturingselement wanneer u het besturingselement invult dat aanvullende metagegevens voor het item bevat. U kunt bijvoorbeeld een FileInfo-object voor bestanden en een DirectoryInfo-object voor mappen toevoegen en vervolgens testen op het itemtype in de tag-eigenschap om extra systeemaanroepen te besparen om die gegevens op te halen wanneer u op het item klikt.


Antwoord 6

Na het combineren van de suggesties van de andere antwoorden, besefte ik dat ik ongeveer hetzelfde kwam als Ronnie Overby’s antwoord . Hier zijn enkele tests om erop te wijzen dat sommige dingen na nadenken:

  1. Mappen kunnen “Extensions” hebben: C:\Temp\folder_with.dot
  2. -bestanden kunnen niet eindigen met een directory-separator (SLASH)
  3. Er zijn technisch twee mojorderscheiders die platformspecifiek zijn – dwz mogen of niet zijn slashes (Path.DirectorySeparatorCharen Path.AltDirectorySeparatorChar)

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

Resultaten

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 

Methode

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

Antwoord 7

Dit was de beste die ik kon bedenken gezien het gedrag van de eigenschappen van het kenmerken:

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

Zo test het uit:

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

Antwoord 8

Dit is wat we gebruiken:

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

Antwoord 9

De meest nauwkeurige benadering is het gebruik van een interoperabiliteitscode uit de 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);

Je zou het dan zo noemen:

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

Antwoord 10

Ik kwam dit tegen toen ik met een soortgelijk probleem werd geconfronteerd, behalve dat ik moest controleren of een pad voor een bestand of map is wanneer dat bestand of die map niet echt bestaat. Er waren een paar opmerkingen over bovenstaande antwoorden waarin werd vermeld dat ze niet zouden werken voor dit scenario. Ik heb een oplossing gevonden (ik gebruik VB.NET, maar je kunt converteren als je dat nodig hebt) die goed lijkt te werken voor mij:

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

Hopelijk kan iemand hier iets aan hebben!


Antwoord 11

zo laat in het spel, ik weet het, maar ik dacht ik deel dit toch even. Als je alleen met de paden als tekenreeksen werkt, is dit een fluitje van een cent:

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

bijvoorbeeld:
ThePath == "C:\SomeFolder\File1.txt"zou dit uiteindelijk worden:

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

Nog een voorbeeld:
ThePath == "C:\SomeFolder\"zou dit worden:

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

En dit zou ook werken zonder de achterste backslash:
ThePath == "C:\SomeFolder"zou dit worden:

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

Houd er rekening mee dat dit alleen werkt met de paden zelf, en niet de relatie tussen het pad en de “fysieke schijf”… dus het kan je niet vertellen of het pad/bestand bestaat of iets dergelijks, maar het kan je zeker vertellen of het pad een map of een bestand is…


Antwoord 12

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

Controleert of de naam van het padbestand een lege tekenreeks is of dat de map bestaat. Op deze manier krijgt u geen fout met bestandskenmerken terwijl u nog steeds redundanties biedt voor een mogelijke bestaande fout.


Antwoord 13

Als je mappen wilt vinden, inclusief de mappen die zijn gemarkeerd als “verborgen” en “systeem”, probeer dan dit (vereist .NET V4):

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

Antwoord 14

Ik had dit nodig, de berichten hielpen, dit brengt het terug naar één regel, en als het pad helemaal geen pad is, keert het gewoon terug en verlaat het de methode. Het lost alle bovenstaande problemen op en heeft ook geen slash nodig.

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

Antwoord 15

Ik zie het, ik ben 10 jaar te laat voor het feest.
Ik werd geconfronteerd met de situatie waarin ik van een eigenschap een bestandsnaam of een volledig bestandspad kan ontvangen. Als er geen pad is opgegeven, moet ik het bestaan ​​van het bestand controleren door een “algemeen” directorypad toe te voegen dat door een andere eigenschap wordt geleverd.

In mijn geval

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

heeft de truc gedaan.
Oké, het is geen magie, maar misschien kan dit iemand een paar minuten tijd besparen.
Aangezien dit slechts een string-parsing is, kunnen Dir-namen met punten valse positieven geven…


Antwoord 16

Ik gebruik het volgende, het test ook de extensie, wat betekent dat het kan worden gebruikt om te testen of het opgegeven pad een bestand is, maar een bestand dat niet bestaat.

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

Antwoord 17

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

Antwoord 18

Met het geselecteerde antwoord op dit bericht heb ik de opmerkingen bekeken en geloofd aan
@ŞafakGür, @Anthony en @Quinn Wilson voor hun info-bits die me naar dit verbeterde antwoord hebben geleid dat ik heb geschreven en getest:

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

Antwoord 19

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

Antwoord 20

Heel laat op het feest hier, maar ik heb ontdekt dat de Nullable<Boolean>-retourwaarde behoorlijk lelijk is – IsDirectory(string path)retourneert nullis niet gelijk aan een niet-bestaand pad zonder uitgebreid commentaar, dus ik heb het volgende bedacht:

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

Deze hulpmethode is zo geschreven dat deze uitgebreid en beknopt genoeg is om de bedoeling te begrijpen wanneer u deze voor het eerst leest.

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

Antwoord 21

Gewoon een randgeval toevoegen – ‘Mapselectie’. in pad

In mijn app krijg ik recent geopende paden die aan mij zijn doorgegeven, waarvan sommige ‘Mapselectie’ hebben. aan het einde.

Sommige FileOpenDialogs en WinMergevoegen “Mapselectie” toe. naar paden (het is waar).

Maar onder Windows OS ‘Mapselectie’. is geen aanbevolen bestands- of mapnaam (zoals in niet doen, ooit – schudt vuist).
Zoals hier gezegd: http://msdn.microsoft. com/nl-nl/bibliotheek/aa365247%28VS.85%29.aspx

Beëindig een bestands- of mapnaam niet met een spatie of een punt. Hoewel het onderliggende bestandssysteem dergelijke namen mogelijk ondersteunt, doen de Windows-shell en gebruikersinterface dat niet. Het is echter acceptabel om een ​​punt op te geven als het eerste teken van een naam. Bijvoorbeeld “.temp”.

Dus terwijl ‘Mapselectie’. mag nietworden gebruikt, het kanwel. (geweldig).

Genoeg uitleg – mijn code (ik hou veel van opsommingen):

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

Antwoord 22

Zou dit niet werken?

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

Other episodes