วิธีที่ดีกว่าในการตรวจสอบว่า Path เป็นไฟล์หรือ Directory


382

ฉันกำลังประมวลผล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 แบบมาตรฐานเพื่อจัดการกับสิ่งนี้ แต่ฉันไม่สามารถทำได้ วิธีการดังกล่าวมีอยู่จริงหรือไม่และถ้าไม่มีความหมายที่ตรงไปตรงมาที่สุดคือการกำหนดว่าเส้นทางเป็นไฟล์หรือไดเรกทอรี


8
ใครสามารถแก้ไขชื่อคำถามเพื่อระบุไฟล์ / ไดเรกทอรี"ที่มีอยู่" ? คำตอบทั้งหมดนำไปใช้กับพา ธ สำหรับไฟล์ / ไดเรกทอรีที่อยู่บนดิสก์
Jake Berger

1
@ jberger โปรดดูคำตอบของฉันด้านล่าง ฉันพบวิธีที่จะทำให้สิ่งนี้สำเร็จสำหรับพา ธ ของไฟล์ / โฟลเดอร์ซึ่งอาจมีหรือไม่มีอยู่
lhan


คุณจะเติมมุมมองต้นไม้นี้อย่างไร คุณได้รับเส้นทางจากมันได้อย่างไร
Random832

คำตอบ:


594

จากวิธีการบอกว่าพา ธ เป็นไฟล์หรือไดเรกทอรี :

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

8
+1 นี่เป็นวิธีที่ดีกว่าและเร็วกว่าโซลูชันที่ฉันเสนอ
Andrew Hare

6
@ KeyMs92 คณิตศาสตร์ระดับบิตมัน โดยทั่วไป attr คือค่าไบนารีบางตัวที่มีความหมายหนึ่งบิต "นี่คือไดเรกทอรี" ค่าที่เหมาะสมและ&ตัวดำเนินการจะคืนค่าไบนารีโดยที่จะเปิดเฉพาะบิตที่อยู่ใน (1) ทั้งในตัวถูกดำเนินการ ในกรณีนี้การทำ bitwise และการดำเนินการกับattrและFileAttributes.Directoryค่าจะส่งกลับค่าของFileAttributes.Directoryถ้าไดเรกทอรีของแอตทริบิวต์ของแฟ้มบิตเปิดอยู่ ดูen.wikipedia.org/wiki/Bitwise_operationสำหรับคำอธิบายที่ดีกว่า
Kyle Trauberman

6
@jberger หากเส้นทางที่ไม่ได้อยู่แล้วก็ไม่ชัดเจนว่าC:\Tempหมายถึงไดเรกทอรีที่เรียกว่าหรือไฟล์ที่เรียกว่าTemp Tempรหัสหมายถึงการทำอะไร
ta.speot.is

26
@Key: หลังจาก. NET 4.0 attr.HasFlag(FileAttributes.Directory)สามารถใช้แทนได้
ŞafakGür

13
@ ŞafakGür: อย่าทำสิ่งนี้ภายในวงที่ไวต่อเวลา attr.HasFlag () ช้าเหมือนนรกและใช้ Reflection สำหรับการโทรแต่ละครั้ง
springy76

247

วิธีการเกี่ยวกับการใช้งานเหล่านี้?

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

43
File.GetAttributes()นี้ยังมีประโยชน์จากการไม่ขว้างปายกเว้นบนเส้นทางที่ไม่ถูกต้องซึ่งแตกต่างจาก
Deanna

ฉันใช้ไลบรารี Long Path จาก BCL bcl.codeplex.com/ในโครงการของฉันดังนั้นจึงไม่มีวิธีรับแอตทริบิวต์ของไฟล์ แต่การเรียก Exist นั้นเป็นวิธีที่ดี
Puterdo Borato

4
@ jberger ฉันคาดว่าจะใช้งานไม่ได้กับพา ธ ไปยังไฟล์ / โฟลเดอร์ที่ไม่มีอยู่จริง File.Exists ("c: \\ temp \\ nonexistant.txt") ควรคืนค่าเท็จตามที่ควรเป็น
michaelkoss

12
หากคุณกังวลเกี่ยวกับไฟล์ / โฟลเดอร์ที่ไม่มีอยู่ลองดูสิ 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 }
ดัสตินทาวน์เซนด์

1
รายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้อยู่ที่msdn.microsoft.com/en-us/library/…
Moji

20

มีเพียงบรรทัดนี้เท่านั้นที่คุณจะได้รับหากเส้นทางเป็นไดเรกทอรีหรือไฟล์:

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

4
ใจคุณต้องการอย่างน้อย. NET 4.0 สำหรับเรื่องนี้ นอกจากนี้สิ่งนี้จะเกิดการระเบิดหากเส้นทางไม่ใช่เส้นทางที่ถูกต้อง
nawfal

ใช้วัตถุ FileInfo เพื่อตรวจสอบว่ามีเส้นทางอยู่หรือไม่: FileInfo pFinfo = new FileInfo (FList [0]); if (pFinfo.Exists) {if (File.GetAttributes (FList [0]). HasFlag (FileAttributes.Directory)) {}} อันนี้ใช้ได้สำหรับฉัน
Michael Stimson

หากคุณได้สร้างวัตถุ FileInfo แล้วและใช้คุณสมบัติ Exists ของคุณสมบัติแล้วทำไมไม่เข้าถึงคุณสมบัติ Attribute แทนการใช้วิธีการ File.GetAttributes () แบบคงที่?
dynamichael

10

นี่คือของฉัน:

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

มันคล้ายกับคำตอบของผู้อื่น แต่ไม่เหมือนกันทั้งหมด


3
ในทางเทคนิคคุณควรใช้Path.DirectorySeparatorCharและPath.AltDirectorySeparatorChar
drzaus

1
ความคิดที่จะเดาเจตนานี้น่าสนใจ IMHO ดีกว่าที่จะแบ่งออกเป็นสองวิธี วิธีที่หนึ่งทำการทดสอบการมีอยู่ส่งคืนบูลีนที่ไม่มีค่า หากผู้เรียกต้องการให้ส่วน "เดา" เป็นผลที่เป็นโมฆะจาก One ให้เรียกวิธีที่สองซึ่งจะเป็นการเดา
ToolmakerSteve

2
ฉันจะเขียนสิ่งนี้เพื่อคืน tuple ด้วยไม่ว่าจะเดาได้หรือไม่
Ronnie Overby

1
"ถ้ามีนามสกุลแล้วมันเป็นไฟล์" - นี่ไม่เป็นความจริง ไฟล์ไม่จำเป็นต้องมีนามสกุล (แม้ใน windows) และไดเรกทอรีสามารถมี "นามสกุล" ตัวอย่างเช่นนี่อาจเป็นไฟล์หรือไดเรกทอรี: "C: \ New folder.log"
bytedev

2
@bytedev ฉันรู้ว่า แต่ ณ จุดนั้นในฟังก์ชั่นรหัสจะคาดเดาความตั้งใจ มีแม้กระทั่งความคิดเห็นที่บอกเช่นนั้น ไฟล์ส่วนใหญ่มีนามสกุล ไดเรกทอรีส่วนใหญ่ทำไม่ได้
Ronnie Overby

7

เป็นอีกทางเลือกหนึ่งสำหรับ Directory.Exists () คุณสามารถใช้เมธอด File.GetAttributes () เพื่อรับคุณสมบัติของไฟล์หรือไดเรกทอรีดังนั้นคุณสามารถสร้างวิธีการช่วยเหลือเช่นนี้:

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

คุณสามารถลองเพิ่มวัตถุไปยังคุณสมบัติแท็กของตัวควบคุม TreeView เมื่อเติมข้อมูลตัวควบคุมที่มีข้อมูลเมตาเพิ่มเติมสำหรับรายการ ตัวอย่างเช่นคุณสามารถเพิ่มวัตถุ FileInfo สำหรับไฟล์และวัตถุ DirectoryInfo สำหรับไดเรกทอรีจากนั้นทดสอบประเภทรายการในคุณสมบัติแท็กเพื่อบันทึกการเรียกระบบเพิ่มเติมเพื่อรับข้อมูลนั้นเมื่อคลิกที่รายการ


2
นี่แตกต่างจากคำตอบ
Jake Berger

6
แทนที่จะเป็นบล็อกตรรกะที่น่ากลัวลองisDirectory = (fa & FileAttributes.Directory) != 0);
Immortal Blue

5

นี่คือสิ่งที่ดีที่สุดที่ฉันจะได้รับเมื่อมีพฤติกรรมของคุณสมบัติการอยู่และแอตทริบิวต์:

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

5

หลังจากการรวมข้อเสนอแนะจากคำตอบอื่น ๆ ฉันรู้ฉันมากับเกี่ยวกับสิ่งเดียวกันเป็นคำตอบของรอนนี่ Overby นี่คือการทดสอบบางอย่างเพื่อชี้ให้เห็นสิ่งที่ควรพิจารณา:

  1. โฟลเดอร์สามารถมี "ส่วนขยาย": C:\Temp\folder_with.dot
  2. ไฟล์ไม่สามารถลงท้ายด้วยตัวคั่นไดเรกทอรี (เครื่องหมายทับ)
  3. ในทางเทคนิคมีสองตัวคั่นไดเรกทอรีซึ่งเป็นแพลตฟอร์มเฉพาะ - เช่นอาจหรืออาจไม่ทับ ( Path.DirectorySeparatorCharและPath.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)
{
    // /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;
}

Path.DirectorySeparatorChar.ToString()แทนที่จะเป็นสตริง concat ด้วย""?
Gone Coding

@GoneCoding อาจจะ; ในเวลาที่ฉันทำงานกับคุณสมบัติที่เป็นโมฆะจำนวนมากดังนั้นฉันจึงติดนิสัย "concat with string ว่างเปล่า" แทนที่จะกังวลเกี่ยวกับการตรวจสอบ null นอกจากนี้คุณยังสามารถทำnew String(Path.DirectorySeparatorChar, 1)ในฐานะที่เป็นสิ่งที่ToStringไม่ถ้าคุณต้องการที่จะได้รับจริงๆที่ดีที่สุด
drzaus

4

วิธีที่แม่นยำที่สุดจะใช้รหัส interop จาก 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);
}

31
น่าเกลียด ฉันเกลียดการทำงานร่วมกันเพื่อทำงานง่ายๆเหล่านี้ และมันไม่ได้พกพา และมันน่าเกลียด ฉันไม่ได้บอกว่ามันน่าเกลียด? :)
Ignacio Soler Garcia

5
@SoMoS มันอาจจะ "น่าเกลียด" ในความคิดของคุณ แต่มันก็ยังเป็นวิธีที่แม่นยำที่สุด ใช่ไม่ใช่โซลูชันแบบพกพา แต่นั่นไม่ใช่คำถามที่ถาม
Scott Dorman

8
คุณหมายถึงอะไรอย่างแม่นยำ มันให้ผลลัพธ์เช่นเดียวกับคำตอบจาก Quinn Wilson และต้องการ interop ซึ่งแบ่งการพกพา สำหรับฉันแล้วมันแม่นยำเท่ากับโซลูชันอื่น ๆ และมีผลข้างเคียงที่ผู้อื่นทำไม่ได้
Ignacio Soler Garcia

7
Framework Framework มีให้ทำเช่นนี้ การใช้งาน Interop ไม่ใช่หนทางที่จะไป
TomXP411

5
ใช่ใช้งานได้ แต่ไม่ใช่โซลูชันที่ "แม่นยำที่สุด" - ไม่มากไปกว่าการใช้. NET Framework ที่มีอยู่ แต่คุณใช้รหัส 6 บรรทัดเพื่อแทนที่สิ่งที่สามารถทำได้ในหนึ่งบรรทัดด้วย. NET Framework และล็อคตัวเองในการใช้ Windows เท่านั้นเมื่อเทียบกับการเปิดความสามารถในการพอร์ตนี้ด้วยโครงการโมโน อย่าใช้ Interop เมื่อ. NET Framework นำเสนอโซลูชันที่หรูหรากว่า
Russ

2

นี่คือสิ่งที่เราใช้:

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

  }

}

2

ฉันมาข้ามนี้เมื่อเผชิญปัญหาที่คล้ายกันยกเว้นผมจำเป็นต้องมีการตรวจสอบว่าเส้นทางสำหรับไฟล์หรือโฟลเดอร์เมื่อที่ไฟล์หรือโฟลเดอร์อาจไม่อยู่จริง มีความคิดเห็นเล็กน้อยเกี่ยวกับคำตอบข้างต้นที่กล่าวถึงว่าพวกเขาจะไม่ทำงานสำหรับสถานการณ์นี้ ฉันพบวิธีแก้ปัญหา (ฉันใช้ 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

หวังว่านี่จะเป็นประโยชน์กับใครบางคน!


1
คุณได้ลองใช้Path.HasExtension แล้วหรือยัง
Jake Berger

หากไม่มีอยู่แสดงว่าไม่ใช่ไฟล์หรือไดเรกทอรี ชื่อใด ๆ ที่สามารถสร้างเป็นทั้ง หากคุณตั้งใจจะสร้างมันขึ้นมาคุณควรจะรู้ว่าคุณกำลังสร้างอะไรและถ้าคุณไม่ทำคุณอาจต้องการข้อมูลนี้ทำไม
Random832

8
โฟลเดอร์สามารถจะตั้งชื่อtest.txtและไฟล์สามารถจะตั้งชื่อtest- ในกรณีเหล่านี้รหัสของคุณจะกลับมาผลที่ไม่ถูกต้อง
สเตฟานบาวเออร์

2
มีวิธีการที่มีอยู่ในคลาส System.IO.FIle และ System.IO.Directory นั่นคือสิ่งที่ต้องทำ ไดเรกทอรีสามารถมีส่วนขยาย; ฉันเห็นมันบ่อยครั้ง
TomXP411

2

สายเกินไปในเกมที่ฉันรู้ แต่คิดว่าฉันจะแบ่งปันมันต่อไป หากคุณกำลังทำงานกับพา ธ เป็นสตริงการหาสิ่งนี้ง่ายเหมือนกับพาย:

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)

โปรดจำไว้ว่านี่ใช้งานได้กับเส้นทางเท่านั้นไม่ใช่ความสัมพันธ์ระหว่างเส้นทางและ "ฟิสิคัลดิสก์" ... ดังนั้นจึงไม่สามารถบอกคุณได้ว่ามีเส้นทาง / ไฟล์อยู่หรืออะไรอย่างนั้น แต่แน่ใจ สามารถบอกคุณได้ว่าเส้นทางเป็นโฟลเดอร์หรือไฟล์ ...


2
ไม่ทำงานSystem.IO.FileSystemWatcherเนื่องจากเมื่อไดเรกทอรีถูกลบมันจะส่งc:\my_directoryเป็นอาร์กิวเมนต์ซึ่งเหมือนกันเมื่อc:\my_directoryลบไฟล์ส่วนขยายที่น้อยลง
Ray Cheng

GetDirectoryName('C:\SomeFolder')ส่งคืน'C:\'ดังนั้นกรณีสุดท้ายของคุณไม่ทำงาน สิ่งนี้จะไม่แยกความแตกต่างระหว่างไดเรกทอรีและไฟล์ที่ไม่มีส่วนขยาย
ลูซี่

คุณผิดสมมติว่าเส้นทางไดเรกทอรีจะรวมถึงสุดท้าย "\" ยกตัวอย่างเช่นจะกลับมาPath.GetDirectoryName("C:\SomeFolder\SomeSubFolder") C:\SomeFolderขอให้สังเกตว่าตัวอย่างของคุณเองของสิ่งที่ GetDirectoryName ส่งกลับแสดงว่ามันส่งคืนเส้นทางที่ไม่สิ้นสุดในแบ็กสแลช ซึ่งหมายความว่าถ้ามีคนใช้ GetDirectoryName ที่อื่นเพื่อรับเส้นทางไดเรกทอรีจากนั้นดึงข้อมูลไปยังวิธีการของคุณพวกเขาจะได้รับคำตอบที่ผิด
ToolmakerSteve

1

หากคุณต้องการค้นหาไดเรกทอรีรวมถึงที่มีการทำเครื่องหมาย "ซ่อน" และ "ระบบ" ลองนี้ (ต้อง. NET V4):

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

1

ฉันต้องการสิ่งนี้โพสต์ช่วยนี่ทำให้มันเป็นหนึ่งบรรทัดและถ้าเส้นทางไม่ใช่เส้นทางเลยมันแค่ส่งกลับและออกจากวิธี มันตอบโจทย์ทุกข้อที่กล่าวมาข้างต้นไม่จำเป็นต้องใช้เครื่องหมายสแลชต่อท้าย

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

0

ฉันใช้สิ่งต่อไปนี้นอกจากนี้ยังทดสอบส่วนขยายซึ่งหมายความว่าสามารถใช้สำหรับการทดสอบได้หากเส้นทางที่ให้มาเป็นไฟล์ แต่เป็นไฟล์ที่ไม่มีอยู่จริง

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

1
FileInfo Extension คือ (IMAO) ตัวเลือกที่ดีในการตรวจสอบเส้นทางที่ไม่มีอยู่จริง
dataCore

2
เงื่อนไขที่สองของคุณ (อย่างอื่น) ส่งกลิ่น ถ้าไม่ใช่ไฟล์ที่มีอยู่คุณก็ไม่รู้ว่ามันจะเป็นอย่างไร (ไดเรกทอรีสามารถลงท้ายด้วยบางสิ่งเช่น ".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));
          }
     }
}

0

ใช้คำตอบที่เลือกในโพสต์นี้ฉันดูความคิดเห็นและให้ความเชื่อถือกับ @ Ş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;
    }

ดูเหมือนว่าจะสิ้นเปลืองในการตรวจสอบแอตทริบิวต์หลังจากตรวจสอบ Directory / File Exists () แล้วใช่ไหม สองสายเหล่านี้เพียงลำพังทำงานทุกอย่างที่จำเป็นที่นี่
Gone Coding

0

อาจเป็นเพราะ 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;
    }

0

ฉันเห็นว่าฉันไปปาร์ตี้เกิน 10 ปีแล้ว ฉันกำลังเผชิญสถานการณ์ซึ่งจากสถานที่ให้บริการบางแห่งฉันสามารถรับชื่อไฟล์หรือเส้นทางแบบเต็ม หากไม่มีเส้นทางให้ฉันต้องตรวจสอบไฟล์ที่มีอยู่โดยแนบไดเรกทอรีเส้นทางทั่วโลกโดยคุณสมบัติอื่น

ในกรณีของฉัน

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

ทำเคล็ดลับ ตกลงมันไม่ได้วิเศษ แต่บางทีมันอาจช่วยให้ใครบางคนหาเวลาได้ไม่กี่นาที เนื่องจากนี่เป็นเพียงการแยกสตริงดังนั้นชื่อ Dir ที่มีจุดอาจให้ผลบวก ...


0

ดึกมากไปงานปาร์ตี้ที่นี่ แต่ฉันพบว่า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);
    }
}

วิธีใช้ตัวช่วยนี้ถูกเขียนขึ้นเพื่อให้ละเอียดและกระชับพอที่จะเข้าใจเจตนาในครั้งแรกที่คุณอ่าน

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

-4

มันจะไม่ทำงานเหรอ

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

1
สิ่งนี้จะไม่ทำงานเพียงเพราะชื่อโฟลเดอร์สามารถมีจุดในช่วงเวลานั้นได้
KSib

นอกจากนี้ไฟล์ไม่จำเป็นต้องมีจุดในไฟล์
Keith Pinson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.