2009-01-13 33 views
66

Tôi có một đường dẫn và tôi cần phải xác định xem đó có phải là một thư mục hoặc tệp hay không..NET Làm cách nào để kiểm tra xem đường dẫn có phải là tệp hay không chứ không phải thư mục?

Đây có phải là cách tốt nhất để xác định xem đường dẫn có phải là tệp không?

string file = @"C:\Test\foo.txt"; 

bool isFile = !System.IO.Directory.Exists(file) && 
         System.IO.File.Exists(file); 

Đối với thư mục, tôi sẽ đảo ngược logic.

string directory = @"C:\Test"; 

bool isDirectory = System.IO.Directory.Exists(directory) && 
          !System.IO.File.Exists(directory); 

Nếu cả hai không tồn tại thì tôi sẽ không làm chi nhánh. Vì vậy, giả sử cả hai đều tồn tại.

+0

http://stackoverflow.com/a/17198139/128506 – HAL9000

+0

có thể trùng lặp của (http://stackoverflow.com/questions/1395205/better-way-to-check-if-a-path-is-a-file-or-a-directory) – DavidRR

Trả lời

101

Sử dụng:

System.IO.File.GetAttributes(string path) 

và kiểm tra xem trở FileAttributes kết quả chứa các giá trị FileAttributes.Directory:

bool isDir = (File.GetAttributes(path) & FileAttributes.Directory) 
       == FileAttributes.Directory; 
+14

Chỉ cần chắc chắn rằng bạn làm điều này trong một try/catch, kể từ khi con đường có thể thậm chí không tồn tại. – LBushkin

+0

Điều gì xảy ra nếu đường dẫn có ký tự đại diện trong đó? Tôi nhận được một đối số nhân vật bất hợp pháp, nhưng nếu tôi sử dụng ký tự đại diện và đó là con đường hợp pháp cho người dùng của tôi thì sao? –

10

Bạn có thể làm điều này với một số mã interop:

[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 
    [return: MarshalAsAttribute(UnmanagedType.Bool)] 
    public static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath); 

Để làm rõ thêm một số ý kiến ​​...

Giới thiệu unmanaged code trong này không phải là bất kỳ inherintly nguy hiểm hơn bất kỳ khác tập tin hoặc I/O liên quan đến các cuộc gọi trong .NET kể từ khi họ ultimatley tất cả các cuộc gọi vào mã không được quản lý.

Đây là một cuộc gọi hàm duy nhất sử dụng chuỗi. Bạn không giới thiệu bất kỳ loại dữ liệu mới nào và/hoặc sử dụng bộ nhớ bằng cách gọi hàm này. Có, bạn cần phải dựa vào mã không được quản lý để dọn dẹp đúng cách, nhưng cuối cùng bạn có sự phụ thuộc đó vào hầu hết các cuộc gọi liên quan đến I/O.

Để tham khảo, đây là đoạn code để File.GetAttributes (string path) từ Reflector:

public static FileAttributes GetAttributes(string path) 
{ 
    string fullPathInternal = Path.GetFullPathInternal(path); 
    new FileIOPermission(FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand(); 
    Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); 
    int errorCode = FillAttributeInfo(fullPathInternal, ref data, false, true); 
    if (errorCode != 0) 
    { 
     __Error.WinIOError(errorCode, fullPathInternal); 
    } 
    return (FileAttributes) data.fileAttributes; 
} 

Như bạn thấy, nó cũng được gọi vào mã không được quản lý để lấy các thuộc tính tập tin, do đó, các tranh luận về việc giới thiệu mã không được quản lý là nguy hiểm là không hợp lệ. Tương tự như vậy, lập luận về việc ở lại hoàn toàn trong mã được quản lý. Không có triển khai mã được quản lý để thực hiện việc này. Ngay cả gọi File.GetAttributes() như các câu trả lời khác đề xuất có cùng một "vấn đề" gọi mã unmanged và tôi tin rằng đây là phương pháp đáng tin cậy hơn để thực hiện xác định nếu một con đường là một thư mục.

Chỉnh sửa Để trả lời nhận xét của @Christian K về CAS. Tôi tin rằng lý do duy nhất GetAttributes làm cho nhu cầu bảo mật là bởi vì nó cần phải đọc các thuộc tính của tập tin để nó muốn đảm bảo rằng mã gọi có quyền làm như vậy. Điều này không giống như kiểm tra hệ điều hành bên dưới (nếu có). Bạn luôn có thể tạo ra một hàm bao quanh xung quanh cuộc gọi P/Invoke đến PathIsDirectory cũng yêu cầu các quyền CAS nhất định, nếu cần thiết.

+2

Điều đó có vẻ như phân bổ công việc để tìm ra nếu một đường dẫn là một tệp hoặc thư mục. –

+0

Làm thế nào mà có rất nhiều công việc? Bạn khai báo một hàm được nhập duy nhất và sau đó có thể gọi nó như thể nó là một phương thức gốc. –

+2

Tôi không thấy lý do tại sao điều này được giảm giá, mặc dù nó sẽ đơn giản hơn nhiều để ở lại trong mã được quản lý bằng cách sử dụng chức năng .NET. –

7

Giả sử thư mục tồn tại ...

bool isDir = (File.GetAttributes(path) & FileAttributes.Directory) 
        == FileAttributes.Directory; 
+0

Nếu đường dẫn không tồn tại, GetAttributes sẽ trả về -1. –

+1

Tài liệu dường như chỉ ra rằng nó sẽ ném một ngoại lệ nếu tệp không tồn tại. http://msdn.microsoft.com/en-us/library/system.io.file.getattributes.aspx – tvanfosson

+0

thử nghiệm của bạn là sai cách xung quanh - đó phải là isDir không phải làFile ... – Alnitak

3

Kiểm tra này ra:

/// <summary> 
/// Returns true if the given file path is a folder. 
/// </summary> 
/// <param name="Path">File path</param> 
/// <returns>True if a folder</returns> 
public bool IsFolder(string path) 
{ 
    return ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory); 
} 

từ http://www.jonasjohn.de/snippets/csharp/is-folder.htm

2

đọc các tập tin thuộc tính:

FileAttributes att = System.IO.File.GetAttributes(PATH_TO_FILE); 

Kiểm tra cho mục cờ.

1

Cho rằng một chuỗi đường dẫn cụ thể không thể đại diện cho cả một thư mục một tệp, sau đó chỉ hoạt động tốt và mở cửa cho các hoạt động khác.

bool isFile = new FileInfo(path).Exists; 
bool isDir = new DirectoryInfo(path).Exists; 

Nếu bạn đang làm việc với các hệ thống tập tin, sử dụng FileInfoDirectoryInfo là đơn giản hơn nhiều so với sử dụng chuỗi.

+0

Xem 0xA3's trả lời, gọi điện thoại tốt hơn một chút. – nawfal

45

Tôi nghĩ rằng đây là cách đơn giản nhất mà bạn chỉ cần hai kiểm tra:

string file = @"C:\tmp"; 
if (System.IO.Directory.Exists(file)) 
{ 
    // do stuff when file is an existing directory 
} 
else if (System.IO.File.Exists(file)) 
{ 
    // do stuff when file is an existing file 
} 
+0

Tôi đã không downvote bạn, nhưng nó được chấp nhận câu trả lời chắc chắn là "đơn giản" và chỉ cần một cuộc gọi (không phải hai). –

+0

Vâng, nó phụ thuộc, cá nhân tôi sẽ xem xét isDir = System.IO.Directory.Exists (tệp) là "đơn giản" hơn giải pháp được chấp nhận. –

+9

Lợi thế của phương pháp này là nó hoạt động ngay cả khi không có mục nhập phù hợp trong hệ thống tập tin nào (nói cách khác, nó không phải là một thư mục hay một tệp); Theo nghĩa đó, nó đơn giản hơn. Ngẫu nhiên, OP cho biết "một con đường", và không phải "một con đường được biết là tồn tại". – Tao

-2

Hmm, nó trông giống như lớp Files (trong java.nio) thực sự có một isDirectory phương pháp tĩnh. Vì vậy, tôi nghĩ rằng bạn thực sự có thể sử dụng như sau: [? Cách tốt hơn để kiểm tra xem một con đường là một tập tin hoặc một thư mục]

Path what = ... 
boolean isDir = Files.isDirectory(what); 
+4

Tìm kiếm giải pháp .NET. –

Các vấn đề liên quan