2013-04-24 37 views
9

Có cách nào để có một trường hợp nhạy cảm Directory.Exists/File.Exists từTrường hợp nhạy cảm Directory.Exists/File.Exists

Directory.Exists(folderPath) 

Directory.Exists(folderPath.ToLower()) 

cả trở true?

Hầu hết thời gian không quan trọng nhưng tôi đang sử dụng macro có vẻ không hoạt động nếu đường dẫn không khớp với trường hợp 100%.

+0

MSDN lưu ý rõ ràng điều này: "Thông số đường dẫn không phân biệt chữ hoa chữ thường.", Hãy xem http://msdn.microsoft.com/en-us/library/system.io.directory.exists.aspx – David

+6

Tôi biết, đó là lý do tại sao tôi hỏi ... – theknut

Trả lời

5

Vì Directory.Exists sử dụng FindFirstFile không phân biệt chữ hoa chữ thường, không. Nhưng bạn có thể PInvoke FindFirstFileEx với một additionalFlags tham số thiết lập để FIND_FIRST_EX_CASE_SENSITIVE

+1

Xin lỗi, có thể là một câu hỏi bãi chứa, nhưng điều này có hiệu quả với C# không? Tất cả các tài liệu tham khảo của bạn liên quan đến C++ * nhầm lẫn * – theknut

+0

Có, bạn có thể sử dụng P/Invoke để gọi ra Win32 từ C#, đọc trên P/Invoke và sau đó kiểm tra liên kết tới pinvoke.net – Matt

+0

+1. @theknut, Liên kết PInvoke cung cấp cho bạn chi tiết về cách làm cho nó có thể gọi được bằng ngôn ngữ C#/khác .Net. –

0

Hãy thử chức năng này:

public static bool FileExistsCaseSensitive(string filename) 
{ 
    string name = Path.GetDirectoryName(filename); 

    return name != null 
      && Array.Exists(Directory.GetFiles(name), s => s == Path.GetFullPath(filename)); 
} 

Cập nhật:

Như đã nêu trong các ý kiến, chỉ này trường hợp kiểm tra trong tên tập tin, không phải trong con đường. Điều này là do phương thức GetFullPath không trả lại đường dẫn gốc của Windows với các trường hợp ban đầu, nhưng là một bản sao của đường dẫn từ tham số.

Ex:

GetFullPath("c:\TEST\file.txt") -> "c:\TEST\file.txt" 
GetFullPath("c:\test\file.txt") -> "c:\test\file.txt" 

Tất cả các phương pháp tôi đã cố gắng làm việc cùng một cách: FileInfo, DirectoryInfo.

Đây là một giải pháp sử dụng một phương pháp kernel32.dll: (? Bool)

[DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    public static extern int GetLongPathName(
     string path, 
     StringBuilder longPath, 
     int longPathLength 
     ); 

    /// <summary> 
    /// Return true if file exists. Non case sensitive by default. 
    /// </summary> 
    /// <param name="filename"></param> 
    /// <param name="caseSensitive"></param> 
    /// <returns></returns> 
    public static bool FileExists(string filename, bool caseSensitive = false) 
    { 
     if (!File.Exists(filename)) 
     { 
      return false; 
     } 

     if (!caseSensitive) 
     { 
      return true; 
     } 

     //check case 
     StringBuilder longPath = new StringBuilder(255); 
     GetLongPathName(Path.GetFullPath(filename), longPath, longPath.Capacity); 

     string realPath = Path.GetDirectoryName(longPath.ToString()); 
     return Array.Exists(Directory.GetFiles(realPath), s => s == filename); 
    } 
+0

Tôi đã thử nó và nó không hoạt động. – LVBen

+0

Nó hoạt động ở đây: Nếu bạn có 'c: \ temp \ TEST.txt', FileExistsCaseSensitive (@ "c: \ temp \ test.txt") sẽ trả về false –

+0

Điều này có hiệu quả đối với tôi. (thử nghiệm trên nền tảng cửa sổ) –

0

Hãy thử những 2 lựa chọn đơn giản mà không cần phải sử dụng PInvoke và trả về một Boolean nullable. Tôi không phải là chuyên gia về chủ đề vì vậy tôi biết nếu đây là mã hiệu quả nhất nhưng nó hoạt động cho tôi.

Chỉ cần vượt qua đường dẫn và nếu kết quả là rỗng (HasValue = false) không tìm thấy kết quả phù hợp, nếu kết quả là sai thì có kết quả khớp chính xác, nếu không thì đúng là trùng khớp với trường hợp khác biệt.

Các phương thức GetFiles, GetDirectories và GetDrives đều trả về trường hợp chính xác như được lưu trên hệ thống tệp của bạn để bạn có thể sử dụng phương pháp so sánh phân biệt chữ hoa chữ thường.

NB: đối với trường hợp đường dẫn là một ổ đĩa chính xác (ví dụ: @ "C: \") Tôi phải sử dụng cách tiếp cận hơi khác.

using System.IO; 
class MyFolderFileHelper { 
    public static bool? FileExistsWithDifferentCase(string fileName) 
    { 
     bool? result = null; 
     if (File.Exists(fileName)) 
     { 
      result = false; 
      string directory = Path.GetDirectoryName(fileName); 
      string fileTitle = Path.GetFileName(fileName); 
      string[] files = Directory.GetFiles(directory, fileTitle); 
      if (String.Compare(files[0], fileName, false) != 0) 
       result = true;     
     } 
     return result; 
    } 

    public static bool? DirectoryExistsWithDifferentCase(string directoryName) 
    { 
     bool? result = null; 
     if (Directory.Exists(directoryName)) 
     { 
      result = false; 
      directoryName = directoryName.TrimEnd(Path.DirectorySeparatorChar); 

      int lastPathSeparatorIndex = directoryName.LastIndexOf(Path.DirectorySeparatorChar); 
      if (lastPathSeparatorIndex >= 0) 
      {      
       string baseDirectory = directoryName.Substring(lastPathSeparatorIndex + 1); 
       string parentDirectory = directoryName.Substring(0, lastPathSeparatorIndex); 

       string[] directories = Directory.GetDirectories(parentDirectory, baseDirectory); 
       if (String.Compare(directories[0], directoryName, false) != 0) 
        result = true; 
      } 
      else 
      { 
       //if directory is a drive 
       directoryName += Path.DirectorySeparatorChar.ToString(); 
       DriveInfo[] drives = DriveInfo.GetDrives(); 
       foreach(DriveInfo driveInfo in drives) 
       { 
        if (String.Compare(driveInfo.Name, directoryName, true) == 0) 
        { 
         if (String.Compare(driveInfo.Name, directoryName, false) != 0) 
          result = true; 
         break; 
        } 
       } 

      } 
     } 
     return result; 
    } 
} 
1

Dựa trên các giải pháp của this question, tôi đã viết đoạn code dưới đây là trường hợp nhạy cảm đối với các toàn bộ con đường ngoại trừ hệ Cửa sổ Drive:

static void Main(string[] args) 
    { 
     string file1 = @"D:\tESt\Test.txt"; 
     string file2 = @"d:\Test\test.txt"; 
     string file3 = @"d:\test\notexists.txt"; 

     bool exists1 = Case_Sensitive_File_Exists(file1); 
     bool exists2 = Case_Sensitive_File_Exists(file2); 
     bool exists3 = Case_Sensitive_File_Exists(file3); 

     Console.WriteLine("\n\nPress any key..."); 
     Console.ReadKey(); 
    } 

    static bool Case_Sensitive_File_Exists(string filepath) 
    { 
     string physicalPath = GetWindowsPhysicalPath(filepath); 
     if (physicalPath == null) return false; 
     if (filepath != physicalPath) return false; 
     else return true; 
    } 

tôi sao chép mã cho GetWindowsPhysicalPath(string path) từ the question

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    static extern uint GetLongPathName(string ShortPath, StringBuilder sb, int buffer); 

    [DllImport("kernel32.dll")] 
    static extern uint GetShortPathName(string longpath, StringBuilder sb, int buffer); 

    protected static string GetWindowsPhysicalPath(string path) 
    { 
     StringBuilder builder = new StringBuilder(255); 

     // names with long extension can cause the short name to be actually larger than 
     // the long name. 
     GetShortPathName(path, builder, builder.Capacity); 

     path = builder.ToString(); 

     uint result = GetLongPathName(path, builder, builder.Capacity); 

     if (result > 0 && result < builder.Capacity) 
     { 
      //Success retrieved long file name 
      builder[0] = char.ToLower(builder[0]); 
      return builder.ToString(0, (int)result); 
     } 

     if (result > 0) 
     { 
      //Need more capacity in the buffer 
      //specified in the result variable 
      builder = new StringBuilder((int)result); 
      result = GetLongPathName(path, builder, builder.Capacity); 
      builder[0] = char.ToLower(builder[0]); 
      return builder.ToString(0, (int)result); 
     } 

     return null; 
    } 

Lưu ý vấn đề duy nhất tôi tìm thấy với chức năng này là, các ký tự ổ đĩa dường như luôn luôn trong chữ thường. Ví dụ: đường dẫn vật lý trên Windows là: D:\Test\test.txt, các GetWindowsPhysicalPath(string path) hàm trả d:\Test\test.txt

+1

Id khuyên bạn nên tạo trường cho '[ThreadStatic] StringBuilder _builder = new StringBuilder (255);' và do đó tránh thêm phân bổ cho mỗi cuộc gọi. Trên thực tế .. loại bỏ phân bổ sẽ là một thay đổi lớn hơn một chút so với chỉ ... hm. – James

0

Nếu đường dẫn (tương đối hoặc tuyệt đối) của tập tin của bạn là:

string AssetPath = "..."; 

Sau đây đảm bảo rằng các tập tin cả hai tồn tại và có vỏ chính xác:

if(File.Exists(AssetPath) && Path.GetFullPath(AssetPath) == Directory.GetFiles(Path.GetDirectoryName(Path.GetFullPath(AssetPath)), Path.GetFileName(Path.GetFullPath(AssetPath))).Single()) 
{ 
} 

Tận hưởng!

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