Lepszy sposób sprawdzenia, czy ścieżka jest plikiem czy katalogiem?

382

Przetwarzam TreeViewkatalogi i pliki. Użytkownik może wybrać plik lub katalog, a następnie coś z nim zrobić. To wymaga ode mnie metody, która wykonuje różne działania w zależności od wyboru użytkownika.

W tej chwili robię coś takiego, aby ustalić, czy ścieżka jest plikiem, czy katalogiem:

bool bIsFile = false;
bool bIsDirectory = false;

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

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

Nie mogę się oprzeć wrażeniu, że jest na to lepszy sposób! Miałem nadzieję znaleźć standardową metodę .NET do obsługi tego, ale nie byłem w stanie tego zrobić. Czy taka metoda istnieje, a jeśli nie, jaki jest najprostszy sposób ustalenia, czy ścieżka jest plikiem czy katalogiem?

SnAzBaZ
źródło
8
Czy ktoś może edytować tytuł pytania, aby określić „istniejący” plik / katalog? Wszystkie odpowiedzi dotyczą ścieżki do pliku / katalogu na dysku.
Jake Berger,
1
@ jberger zapoznaj się z moją odpowiedzią poniżej. Znalazłem sposób na osiągnięcie tego w przypadku ścieżek plików / folderów, które mogą istnieć lub nie.
lhan
Jak wypełniasz ten widok drzewa? Jak z tego wyjść?
Random832

Odpowiedzi:

594

Od Jak stwierdzić, czy ścieżka jest plikiem czy katalogiem :

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

Aktualizacja dla .NET 4.0+

Zgodnie z poniższymi komentarzami, jeśli korzystasz z platformy .NET 4.0 lub nowszej (a maksymalna wydajność nie jest krytyczna), możesz napisać kod w czystszy sposób:

// 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");
Quinn Wilson
źródło
8
+1 To jest lepsze podejście i jest znacznie szybsze niż rozwiązanie, które zaproponowałem.
Andrew Hare,
6
@ KeyMs92 Jego matematyka bitowa. Zasadniczo, attr to pewna wartość binarna z jednym bitem oznaczającym „to katalog”. Bitowy i &operator zwrócą wartość binarną, w której tylko bity, które są włączone (1) w obu operandach, są włączone. W takim przypadku wykonanie bitowe i wykonanie operacji przeciw, attra FileAttributes.Directorywartość zwróci wartość, FileAttributes.Directoryjeśli bit atrybutu pliku katalogu jest włączony. Aby uzyskać lepsze wyjaśnienie, zobacz en.wikipedia.org/wiki/Bitwise_operation .
Kyle Trauberman
6
@ jberger Jeśli ścieżka nie istnieje, nie jest jasne, czy C:\Tempodnosi się do katalogu o nazwie, Tempczy do pliku o nazwie Temp. Do czego służy kod?
ta.speot.is
26
@Klucz: Po .NET 4.0 attr.HasFlag(FileAttributes.Directory)można zamiast niego użyć.
Şafak Gür
13
@ ŞafakGür: Nie rób tego w pętli wrażliwej na czas. attr.HasFlag () działa powoli jak diabli i używa Reflection dla każdego wywołania
springy76
247

Co powiesz na ich użycie?

File.Exists();
Directory.Exists();
llamaoo7
źródło
43
Ma to tę zaletę, że nie rzuca wyjątku na niepoprawną ścieżkę, w przeciwieństwie do File.GetAttributes().
Deanna
Używam biblioteki Long Path z BCL bcl.codeplex.com/… w moim projekcie, więc nie ma sposobu na uzyskanie atrybutów pliku, ale wywołanie Exist jest przyjemnym obejściem.
Puterdo Borato
4
@ jberger Spodziewałbym się, że NIE zadziała w przypadku ścieżek do nieistniejących plików / folderów. File.Exists ("c: \\ temp \\ nonexistant.txt") powinien zwracać false, tak jak to robi.
michaelkoss,
12
Jeśli martwisz się o nieistniejące pliki / foldery, spróbuj tego public static bool? IsDirectory(string path){ if (Directory.Exists(path)) return true; // is a directory else if (File.Exists(path)) return false; // is a file else return null; // is a nothing }
Dustin Townsend
1
Więcej informacji na ten temat można znaleźć na stronie msdn.microsoft.com/en-us/library/…
Moji
20

Za pomocą tylko tego wiersza możesz uzyskać, jeśli ścieżka jest katalogiem lub plikiem:

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)
Gerard Gilabert Canal
źródło
4
Pamiętaj, że potrzebujesz do tego przynajmniej .NET 4.0. To również wybuchnie, jeśli ścieżka nie jest prawidłową ścieżką.
nawfal
Użyj obiektu FileInfo, aby sprawdzić, czy ścieżka istnieje: FileInfo pFinfo = new FileInfo (FList [0]); if (pFinfo.Exists) {if (File.GetAttributes (FList [0]). HasFlag (FileAttributes.Directory)) {}}. Ten działa dla mnie.
Michael Stimson
Jeśli już utworzyłeś obiekt FileInfo i korzystasz z właściwości Exists instancji, dlaczego nie uzyskać dostępu do jej właściwości Attributes zamiast statycznej metody File.GetAttributes ()?
dynamichael
10

To moje:

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

Jest podobny do odpowiedzi innych, ale nie dokładnie taki sam.

Ronnie Overby
źródło
3
Technicznie powinieneś używać Path.DirectorySeparatorChariPath.AltDirectorySeparatorChar
drzaus
1
Ten pomysł odgadnięcia zamiaru jest interesujący. IMHO lepiej podzielić na dwie metody. Metoda pierwsza wykonuje testy egzystencji, zwracając zerowalną wartość logiczną. Jeśli dzwoniący chce wtedy części „zgadnij”, po zerowym wyniku z Jednego, wówczas wywołaj Metodę Drugą, która zgaduje.
ToolmakerSteve,
2
Przepisałbym to, aby zwrócić krotkę z tym, czy zgadł, czy nie.
Ronnie Overby
1
„jeśli ma rozszerzenie, to jest to plik” - to nieprawda. Plik nie musi mieć rozszerzenia (nawet w systemie Windows), a katalog może mieć „rozszerzenie”. Może to być na przykład plik lub katalog: „C: \ New folder.log”
bytedev
2
@bytedev Wiem o tym, ale w tym momencie funkcja zgaduje. Mówi nawet o tym komentarz. Większość plików ma rozszerzenie. Większość katalogów nie.
Ronnie Overby,
7

Alternatywnie do Directory.Exists () można użyć metody File.GetAttributes (), aby uzyskać atrybuty pliku lub katalogu, aby można było utworzyć metodę pomocniczą w następujący sposób:

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

Można również rozważyć dodanie obiektu do właściwości tagu kontrolki TreeView podczas zapełniania kontrolki zawierającej dodatkowe metadane dla elementu. Na przykład można dodać obiekt FileInfo dla plików i obiekt DirectoryInfo dla katalogów, a następnie przetestować typ elementu we właściwości znacznika, aby zapisać wykonywanie dodatkowych wywołań systemowych w celu uzyskania tych danych po kliknięciu elementu.

Michael A. McCloskey
źródło
2
czym to się różni od drugiej odpowiedzi
Jake Berger
6
Zamiast tego okropnego bloku logicznego, spróbujisDirectory = (fa & FileAttributes.Directory) != 0);
Immortal Blue
5

To było najlepsze, jakie mogłem wymyślić, biorąc pod uwagę zachowanie właściwości Exists i 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;
    }
}

Oto jak się to sprawdza:

    [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());
    }
HAL9000
źródło
5

Po połączeniu sugestii z innych odpowiedzi zdałem sobie sprawę, że wpadłem na to samo co odpowiedź Ronniego Overby'ego . Oto kilka testów wskazujących na kilka rzeczy do przemyślenia:

  1. foldery mogą mieć „rozszerzenia”: C:\Temp\folder_with.dot
  2. pliki nie mogą kończyć się separatorem katalogów (ukośnik)
  3. Istnieją dwa technicznie separatory katalogów, które są specyficzne dla platformy - tzn. Mogą być lub nie są ukośnikami ( Path.DirectorySeparatorChari Path.AltDirectorySeparatorChar)

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

Wyniki

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 

metoda

/// <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)
{
    // /programming/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;
}
drzaus
źródło
Path.DirectorySeparatorChar.ToString()zamiast konkatowania ciągów z ""?
Gone Coding
@GoneCoding prawdopodobnie; w tym czasie pracowałem z szeregiem właściwości zerowalnych, więc miałem zwyczaj „konkatować z pustym łańcuchem”, zamiast martwić się o sprawdzenie, czy nie ma wartości zerowej. Możesz również zrobić new String(Path.DirectorySeparatorChar, 1)tak, jak to ToStringdziała, jeśli chcesz naprawdę się zoptymalizować.
drzaus
4

Najdokładniejszym podejściem będzie użycie kodu interop z 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);

Nazwałbyś to tak:

#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);
}
Scott Dorman
źródło
31
Brzydki. Nienawidzę interopu do wykonywania tych prostych zadań. I to nie jest przenośne. i to jest brzydkie. Czy powiedziałem, że to brzydkie? :)
Ignacio Soler Garcia
5
@SoMoS Może to według ciebie być „brzydkie”, ale nadal jest to najdokładniejsze podejście. Tak, to nie jest przenośne rozwiązanie, ale nie o to pytano.
Scott Dorman
8
Co dokładnie masz na myśli jako dokładne? Daje takie same wyniki jak odpowiedź Quinna Wilsona i wymaga interopu, który przerywa przenośność. Dla mnie jest tak dokładny jak inne rozwiązania i ma skutki uboczne, których inni nie.
Ignacio Soler Garcia
7
Do tego celu służy Framework API. Korzystanie z Interopa nie jest dobrym rozwiązaniem.
TomXP411
5
Tak, to działa, ale NIE jest to „najdokładniejsze” rozwiązanie - nie więcej niż przy użyciu istniejącego .NET Framework. Zamiast tego bierzesz 6 linii kodu, aby zastąpić to, co można zrobić w jednym wierszu z .NET Framework, i blokujesz się do korzystania tylko z systemu Windows, w przeciwieństwie do pozostawienia otwartej możliwości przeniesienia tego do Mono Project. Nigdy nie używaj Interop, gdy .NET Framework oferuje bardziej eleganckie rozwiązanie.
Russ
2

Oto, czego używamy:

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

  }

}
PMBottas
źródło
2

Natknąłem się na to, gdy napotkałem podobny problem, z tym, że musiałem sprawdzić, czy istnieje ścieżka do pliku lub folderu, gdy ten plik lub folder może faktycznie nie istnieć . Było kilka komentarzy do odpowiedzi powyżej, które wspominały, że nie będą działać w tym scenariuszu. Znalazłem rozwiązanie (używam VB.NET, ale możesz je przekonwertować, jeśli potrzebujesz), które wydaje mi się działać dobrze:

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

Mam nadzieję, że może to komuś pomóc!

lhan
źródło
1
próbowałeś metody Path.HasExtension ?
Jake Berger,
Jeśli nie istnieje, to nie jest to plik ani katalog. Można utworzyć dowolną nazwę jako jedną z nich. Jeśli zamierzasz go stworzyć, powinieneś wiedzieć, co tworzysz, a jeśli nie, to dlaczego możesz potrzebować tych informacji?
Random832
8
Folder może być nazwany test.txti plik może być nazwany test- w tych przypadkach kod wróci nieprawidłowych wyników
Stephan Bauer
2
W klasach System.IO.FIle i System.IO.Directory istnieje metoda .Exists. to jest to, co należy zrobić. Katalogi mogą mieć rozszerzenia; Często to widzę.
TomXP411
2

bardzo późno w grze, wiem, ale myślałem, że i tak to podzielę. Jeśli pracujesz wyłącznie ze ścieżkami jako ciągami, znalezienie tego jest proste jak ciasto:

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

na przykład: ThePath == "C:\SomeFolder\File1.txt"byłoby tak:

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

Kolejny przykład: ThePath == "C:\SomeFolder\"skończyłby się tak:

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

I to też działałoby bez końcowego ukośnika odwrotnego: w ThePath == "C:\SomeFolder"końcu byłby to:

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

Należy pamiętać, że działa to tylko z samymi ścieżkami, a nie z relacją między ścieżką a „dyskiem fizycznym” ... więc nie może powiedzieć, czy ścieżka / plik istnieje, czy coś podobnego, ale na pewno może powiedzieć, czy ścieżka jest folderem czy plikiem ...

MaxOvrdrv
źródło
2
Nie działa, System.IO.FileSystemWatcherponieważ po usunięciu katalogu wysyła c:\my_directoryjako argument, który jest taki sam, gdy c:\my_directoryusuwany jest plik bez rozszerzenia .
Ray Cheng
GetDirectoryName('C:\SomeFolder')zwraca 'C:\', więc twoja ostatnia sprawa nie działa. Nie rozróżnia to katalogów i plików bez rozszerzeń.
Lucy,
Błędnie zakładasz, że ścieżka katalogu zawsze będzie zawierać końcowe „\”. Na przykład Path.GetDirectoryName("C:\SomeFolder\SomeSubFolder")wróci C:\SomeFolder. Zauważ, że twoje własne przykłady tego, co zwraca GetDirectoryName, pokazują, że zwraca ścieżkę, która nie kończy się odwrotnym ukośnikiem. Oznacza to, że jeśli ktoś użyje GetDirectoryName w innym miejscu, aby uzyskać ścieżkę do katalogu, a następnie poda ją do Twojej metody, otrzyma złą odpowiedź.
ToolmakerSteve
1

Jeśli chcesz znaleźć katalogi, w tym te oznaczone jako „ukryte” i „system”, spróbuj tego (wymaga .NET V4):

FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory)) 
Jamie
źródło
1

Potrzebowałem tego, posty pomogły, to sprowadza się do jednej linii, a jeśli ścieżka wcale nie jest ścieżką, po prostu zwraca i wychodzi z metody. Odpowiada na wszystkie powyższe obawy, nie wymaga również ukośnika końcowego.

if (!Directory.Exists(@"C:\folderName")) return;
Joe Stellato
źródło
0

Korzystam z poniższych, testuje również rozszerzenie, co oznacza, że ​​można go użyć do testowania, czy podana ścieżka to plik, ale plik, który nie istnieje.

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;
}
Stu1983
źródło
1
FileInfo Extension to (IMAO) dobra opcja do sprawdzania nieistniejących ścieżek
dataCore
2
twój drugi warunek (inaczej) jest śmierdzący. jeśli nie jest to istniejący plik, to nie wiesz, co to może być (katalogi mogą kończyć się także na „.txt”).
nawfal
0
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));
          }
     }
}
Diaa Eddin
źródło
0

Korzystając z wybranej odpowiedzi w tym poście, spojrzałem na komentarze i daję wiarygodność @ ŞafakGür, @Anthony i @Quinn Wilson za ich bity informacyjne, które doprowadziły mnie do tej ulepszonej odpowiedzi, którą napisałem i przetestowałem:

    /// <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;
    }
Mike Socha III
źródło
Wydaje się trochę marnotrawstwem sprawdzanie atrybutów po sprawdzeniu, czy istnieje już katalog / plik istnieje ()? Same te dwa połączenia wykonują tutaj całą pracę.
Gone Coding
0

Może dla 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;
    }
Minuta V.
źródło
0

Rozumiem, jestem o 10 lat za późno na przyjęcie. Miałem do czynienia z sytuacją, w której z jakiejś nieruchomości mogę otrzymać nazwę pliku lub pełną ścieżkę pliku. Jeśli nie podano ścieżki, muszę sprawdzić istnienie pliku, dołączając „globalną” ścieżkę katalogu podaną przez inną właściwość.

W moim przypadku

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

wykonał lewę. Ok, to nie jest magia, ale może to uratuje komuś kilka minut na rozgryzienie. Ponieważ jest to tylko parsowanie ciągów, więc nazwy Dir z kropkami mogą dawać fałszywe alarmy ...

dba
źródło
0

Bardzo późno na imprezę tutaj, ale okazało się, że Nullable<Boolean>zwracana wartość jest dość brzydka - IsDirectory(string path)powrót nullnie oznacza nieistniejącej ścieżki bez pełnych komentarzy, więc wymyśliłem następujące:

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

Ta metoda pomocnicza jest napisana tak, aby była wystarczająco szczegółowa i zwięzła, aby zrozumieć intencję przy pierwszym czytaniu.

/// <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
    }
}
martinthebeardy
źródło
-4

Czy to nie zadziała?

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

źródło
1
Nie działałoby to tylko dlatego, że nazwy folderów mogą zawierać kropki
KSib
Również pliki nie muszą zawierać kropek.
Keith Pinson