2009-07-31 10 views
17

tutaj jest problem, mam kilka katalogów jakznormalizowania nazwy katalogów w C#

S: \ Hello \ HI
S: \ hello2 \ hi \ HElloAgain

na pliku System pokazuje te katalogi jak

S: \ cześć \ Hi
S: \ hello2 \ Hi \ helloAgain

Czy istnieje jakaś funkcja w języku C#, która da mi nazwę systemu plików katalogu z właściwą obudową?

+0

Jest nie ma takiej funkcji, a próba normalizacji łańcuchów takich jak "HElloAgain" do "helloAgain" będzie problemem, ponieważ nawet Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase ("HElloAgain") zwróci wartość "Helloagain." –

+0

@Agent, DirectoryInfo. GetDirectories() zwraca foldery w systemie plików: – Kevin

+1

Zaakceptowany, wow, nie miałem pojęcia, że ​​są tu nowe odpowiedzi, dzięki Icemanowi i Bertu za pomoc w rozwiązaniu tego problemu – Tom

Odpowiedz

8

string FileSystemCasing = new System.IO.DirectoryInfo("H:\...").FullName;

Edycja:

jako Lodziarzu wskazał FullName zwróci prawidłowy obudowy tylko jeśli DirectoryInfo (lub w ogóle FileSystemInfo) pochodzi z wywołanie GetDirectories (lub GetFileSystemInfos) sposobu.

Teraz publikuję przetestowane i zoptymalizowane pod kątem wydajności rozwiązanie. Działa dobrze zarówno na ścieżkach katalogów i plików, a także ma pewną odporność na błędy w łańcuchu wejściowym. Jest zoptymalizowany pod kątem "konwersji" pojedynczych ścieżek (nie całego systemu plików) i szybszy niż uzyskanie całego drzewa systemu plików. Oczywiście, jeśli masz do renormalize całego drzewa systemu plików, może wolisz rozwiązanie Iceman, ale i przetestowane na 10000 iteracji na ścieżkach o średnim poziomie deepness, a to trwa tylko kilka sekund;)

private string GetFileSystemCasing(string path) 
    { 
     if (Path.IsPathRooted(path)) 
     { 
      path = path.TrimEnd(Path.DirectorySeparatorChar); // if you type c:\foo\ instead of c:\foo 
      try 
      { 
       string name = Path.GetFileName(path); 
       if (name == "") return path.ToUpper() + Path.DirectorySeparatorChar; // root reached 

       string parent = Path.GetDirectoryName(path); // retrieving parent of element to be corrected 

       parent = GetFileSystemCasing(parent); //to get correct casing on the entire string, and not only on the last element 

       DirectoryInfo diParent = new DirectoryInfo(parent); 
       FileSystemInfo[] fsiChildren = diParent.GetFileSystemInfos(name); 
       FileSystemInfo fsiChild = fsiChildren.First(); 
       return fsiChild.FullName; // coming from GetFileSystemImfos() this has the correct case 
      } 
      catch (Exception ex) { Trace.TraceError(ex.Message); throw new ArgumentException("Invalid path"); } 
      return ""; 
     } 
     else throw new ArgumentException("Absolute path needed, not relative"); 
    } 
+1

To w rzeczywistości nie działa. Zwraca ten sam przypadek, w którym przechodzi do konstruktora DirectoryInfo i ignoruje rzeczywisty przypadek przechowywany w systemie plików, ale jest to przypadek systemu plików, który chce. – Kevin

+0

Masz rację. Zmontowałem, aby przedstawić pełny przykład roboczy. – BertuPG

+1

Przepraszam. Twój pierwszy komentarz wydawał się bardziej wrogi, niż ci się wydawało, i powinienem był pozwolić mu odejść, zamiast rozpoczynać kłótnię. Naprawdę powinienem zostać w Internecie, kiedy jestem zrzędliwy. Podział ścieżki i zdobycie przypadku każdego kawałka jest naprawdę dobrym pomysłem, a to sprawia, że ​​różnica między bolesnym powolnym a użytecznym. Nie mogę przyjąć twojej odpowiedzi, chyba że ją edytujesz, ale to nie powstrzymało mnie przed wznowieniem niektórych twoich innych odpowiedzi. Przepraszam za bycie palantem - jestem ci winien drinka, jeśli kiedykolwiek będziesz w Denver. – Kevin

-1

ten powinien zrobić:

System.IO.Directory.GetFiles("..."); 
+0

Nie widzę, co próbujesz powiedzieć/sugerować To rzuca "Nie można znaleźć część ścieżki "..." ". – binki

+0

@binki To po prostu zwykły angielski. Zamień "..." na dowolny folder, który chcesz przeszukać. –

+0

Wtedy podejrzewam, że źle zinterpretowałeś to pytanie. Kiedy robię 'Directory.GetFiles (@" \ USERS \ OHNOB \ HELLO ")', otrzymuję '{" \ USERS \ OHNOB \ HELLO \ Hi "}' zamiast '{" \ Users \ ohnob \ hello \ Hi " } '. Jestem pewien, że pytanie brzmi, jak zdobyć to ostatnie. – binki

-3

 
     static void Main(string[] args) 
     { 
     string[] paths = new string[] { "S:\hello\Hi", "S:\hello2\Hi\helloAgain" }; 
     foreach(string aPath in paths) 
     { 
      string normalizedPath = NormalizePath(aPath); 
      Console.WriteLine("Previous: '{0}', Normalized: '{1}'", aPath, normalizedPath); 
     } 
     Console.Write("\n\n\nPress any key..."); 
     Console.Read(); 
     }

public static string NormalizePath(string path) 
    { 
    StringBuilder sb = new StringBuilder(path); 
    string[] paths = path.Split('\\'); 
    foreach(string folderName in paths) 
    { 
     string normalizedFolderName = ToProperCase(folderName); 
     sb.Replace(folderName, normalizedFolderName); 
    } 
    return sb.ToString(); 
    } 

    /// <summary> 
    /// Converts a string to first character upper and rest lower (Camel Case). 
    /// </summary> 
    /// <param name="stringValue"></param> 
    /// <returns></returns> 
    public static string ToProperCase(string stringValue) 
    { 
    if(string.IsNullOrEmpty(stringValue)) 
     return stringValue; 

    return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(stringValue.ToLower()); 
    } 

+2

Poprosił o obudowę przechowywaną w systemie plików, niekoniecznie w TitleCasing. – Kevin

4

Oto rozwiązanie proste i stosunkowo szybko, zachować czytania poniżej jakiegoś komentarza:

private static string GetCase(string path) 
{  
    DirectoryInfo dir = new DirectoryInfo(path); 
    if (dir.Exists) 
    { 
    string[] folders = dir.FullName.Split(Path.DirectorySeparatorChar); 
    dir = dir.Root; 

    foreach (var f in folders.Skip(1)) 
    {   
     dir = dir.GetDirectories(f).First(); 
    } 

    return dir.FullName; 
    } 
    else 
    { 
    return path; 
    } 
} 

Podstawową ideą polega na tym, że pobranie podkatalogów z obiektu DirectoryInfo dostaniemy poprawny przypadek, więc wystarczy podzielić nazwę katalogu i przejść od katalogu głównego do katalogu docelowego, uzyskując prawidłowy przypadek w każdym kroku.

Moja początkowa odpowiedź polegała na uzyskaniu obudowy dla każdego folderu na dysku i działała, ale była wolna. Wprowadziłem niewielką poprawę, która zapisywała wyniki, ale wciąż była zbyt powolna do codziennego użytku. Możesz zobaczyć historię edycji tego komentarza, jeśli chcesz to zrobić dla każdej rzeczy na dysku, a nawet wtedy są prawdopodobnie sposoby na przyspieszenie tego kodu. To było "tutaj, jak możesz to zrobić", a nie "tutaj jest świetny sposób na zrobienie tego".

Bertu, w swojej odpowiedzi, wpadł na pomysł podziału ścieżkę do jego składników i uzyskanie kawałek po kawałku obudowy, co skutkuje ogromny wzrost prędkości ponieważ nie jesteś już sprawdzanie wszystko jako w mojej oryginalnej odpowiedzi. Bertu uogólnił także swoje rozwiązanie do robienia plików, a także katalogów. W moich testach powyższy kod (wykorzystujący koncepcję Bertu "dzielę ścieżkę i robię to na kawałki", ale podchodzi do niej iteracyjnie zamiast rekursywnie) działa w około połowie czasu kodu Bertu. Nie jestem pewien, czy to dlatego, że jego metoda obsługuje również pliki, ponieważ jego użycie rekursji wprowadza dodatkowy narzut lub dlatego, że kończy się wywoływaniem w każdej iteracji Path.GetFileName(path) i . W zależności od Twoich konkretnych potrzeb, pewna kombinacja jego odpowiedzi i mojej prawdopodobnie rozwiąże Twój problem, jak to tylko możliwe w języku C#.

W tym pamiętać, należy wspomnieć, że istnieją some limitations do .Net obsługi nazw plików, a ponieważ robi to w .NET wymaga podejmowania wielu obiektów DirectoryInfo, może warto rozważyć kod niezarządzanej jeśli jest to wąskie gardło.

+0

to działa, ale jest PAINFULLY powolny, ponieważ wykonuje pełne skanowanie systemu dla katalogu wyszukiwania i mam ponad 100 katalogów, aby znormalizować – Tom

+0

@ Tom, zobacz moją aktualizację. Powinienem był początkowo pomyśleć o wielu katalogach. – Kevin

+0

@Dom: patrz edycja w MOIM poście! ;) – BertuPG

Powiązane problemy