2013-04-24 17 views
9

Czy istnieje sposób, aby mieć wielkość liter Directory.Exists/File.Exists odwielkość liter Directory.Exists/File.Exists

Directory.Exists(folderPath) 

i

Directory.Exists(folderPath.ToLower()) 

zarówno powrócić true?

W większości przypadków nie ma to znaczenia, ale używam makra, które wydaje się nie działać, jeśli ścieżka nie pasuje do przypadków 100%.

+0

MSDN wyraźnie to zauważyło: "W parametrze ścieżki nie jest rozróżniana wielkość liter.", Zobacz http://msdn.microsoft.com/en-us/library/system.io.directory.exists.aspx – David

+6

Wiem, dlatego proszę ... – theknut

Odpowiedz

5

Ponieważ Directory.Exists używa FindFirstFile, w którym nie jest rozróżniana wielkość liter, nie. Ale można PInvoke FindFirstFileEx z additionalFlags parametr ustawiony FIND_FIRST_EX_CASE_SENSITIVE

+1

Przepraszamy, ale może to być pytanie dump, ale czy to działa dla C#? Wszystkie twoje referencje odnoszą się do C++ * zagmatwany * – theknut

+0

Tak, powinien, możesz użyć P/Invoke, aby wywołać Win32 z C#, przeczytać na P/Invoke, a następnie sprawdzić link do pinvoke.net – Matt

+0

+1. @thenut, link PInvoke daje ci szczegóły, jak sprawić by można było wywoływać w C#/innych językach .Net. –

0

Spróbuj funkcję:

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

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

Aktualizacja:

Jak podano w komentarzach, to tylko przypadki wyboru w pliku, a nie w ścieżka. Wynika to z faktu, że metoda GetFullPath nie zwraca pierwotnej ścieżki systemu Windows z oryginalnymi przypadkami, ale kopię ścieżki z parametru.

Ex:

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

Wszystkie metody próbowałem działają w ten sam sposób: Fileinfo, DirectoryInfo.

Oto rozwiązanie przy użyciu metody 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

Próbowałem go i to nie działa. – LVBen

+0

Działa tutaj: Jeśli masz "c: \ temp \ TEST.txt", FileExistsCaseSensitive (@ "c: \ temp \ test.txt") zwróci false –

+0

To działa dla mnie. (testowane na platformie Windows) –

0

Spróbuj te 2 opcje prostsze, że nie trzeba używać PInvoke i zwracają zerowalne Boolean. Nie jestem ekspertem od tematu, więc wiem, czy jest to najbardziej wydajny kod, ale działa on dla mnie.

Po prostu przekazać ścieżkę i jeśli wynik jest równy null (HasValue = false) nie znaleziono żadnego wyniku, jeśli wynikiem jest wartość false, istnieje dopasowanie ścisłe, w przeciwnym razie, jeśli prawda jest zgodna ze znacznikiem różnicy.

Metody GetFiles, GetDirectories i GetDrives zwracają dokładny przypadek zapisany w systemie plików, dzięki czemu można użyć metody porównywania wielkości liter.

Uwaga: w przypadku, gdy ścieżka jest napędem dokładnym (np. @ "C: \"), muszę zastosować nieco inne podejście.

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

oparciu o rozwiązania this question, napisałem poniższy kod, który jest wielkość liter dla całej ścieżki wyjątkiem listu Okna Dysk:

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

I skopiowany kod GetWindowsPhysicalPath(string path) od 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; 
    } 

Uwaga Jedyny problem, jaki znalazłem w przypadku tej funkcji, to litera dysku wydaje się być zawsze pisana małymi literami. Przykład: Fizyczne ścieżki w systemie Windows to: D:\Test\test.txt funkcja GetWindowsPhysicalPath(string path) zwraca d:\Test\test.txt

+1

Id polecam utworzenie pola dla '[ThreadStatic] StringBuilder _builder = new StringBuilder (255);' i przez to uniknięcie dodawania przydziału do każdego połączenia. Właściwie ... wyeliminowanie przydziałów byłoby nieco większą zmianą niż tylko to ... hm. – James

0

Jeśli (względny lub bezwzględny), ścieżka do pliku jest:

string AssetPath = "..."; 

Poniższa gwarantuje, że plik zarówno istnieje i ma właściwa obudowa:

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

Ciesz się!