2009-01-08 46 views
0

解決在我的文章的底部。IComparer問題+如何在.NET中自然地排序字符串數組(FILE_10> FILE_2)?

或者更具體地說:

我有一大堆的FileInfo對象(我需要的FileInfo對象排除隱藏,系統和重新分析點文件)。

我需要的FileInfo []自然根據他們FileInfo.FullName進行排序。所以FILE_10.ext應該在FILE_2.ext之後。幸運的是,FileInfo []僅包含一個擴展名的文件。

我實現了一個比較器:

/// <summary> 
/// Compares FileInfo objects based on the files full path. 
/// This comparer is flawed in that it will only work correctly 
/// on files with the same extension. 
/// Though that could easily be fixed. 
/// </summary> 
private class FileInfoSorter : IComparer 
{ 

    int IComparer.Compare(Object x, Object y) 
    { 
     FileInfo _x = x as FileInfo; 
     FileInfo _y = y as FileInfo; 

     // FYI: 
     //ExprFileVersion = new Regex("(.*)_([0-9]+)\\.[^\\.]+$", RegexOptions.Compiled); 
     Match m1 = RegExps.ExprFileVersion.Match(_x.FullName); 
     Match m2 = RegExps.ExprFileVersion.Match(_y.FullName); 
     if (m1.Success && m2.Success) // we have versioned files 
     { 
      int n1; 
      int n2; 
      try 
      { 
       n1 = int.Parse(m1.Groups[2].Value); 
      } 
      catch (OverflowException ex) 
      { 
       // Don't know if this works. 
       ex.Data["File"] = _x.FullName; 
       throw; 
      } 

      try 
      { 
       n2 = int.Parse(m2.Groups[2].Value); 
      } 
      catch (OverflowException ex) 
      { 
       // Don't know if this works. 
       ex.Data["File"] = _y.FullName; 
       throw; 
      } 


      string s1 = m1.Groups[1].Value; 
      string s2 = m2.Groups[1].Value; 

      if (s1.Equals(s2)) 
      { 
       return n1.CompareTo(n2); // compare numbers naturally. E.g. 11 > 6       
      } 
      else // not the same base file name. So the version does not matter. 
      { 
       return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName)); 
      } 
     } 
     else // not versioned 
     { 
      return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName)); 
     } 
    } 


} 

現在出現的問題是int.Parse拋出一個OverflowException異常,我沒能趕上在正確的點(它再次出現在return語句的行某種原因,我無法進一步智能處理它,因爲它永遠不會到達那裏)。

的問題是:是否有這樣的事情實現的預比較器?這個例外在有趣的地方出現的原因是什麼?

調用代碼:

IComparer fiComparer = new FileInfoSorter(); 

     try 
     { 
      Array.Sort(filesOfExtInfo, fiComparer); 
     } 
     catch (OverflowException ex) 
     { 
      // Do not know yet if I can use ex.Data in this way. 
      WriteStatusLineAsync("Error: Encountered too large a version number on file: " + ex.Data["File"]); 
     } 

EDIT1:Int.Parse拋出OverflowException異常,當它遇到太大的數目。它不應該定期發生,但我希望它覆蓋。

編輯2:我最終調整了我自己的比較器。從int.Parse中取出,並用零填充以便進行比較。 代碼在這裏:

public class FileInfoSorter : IComparer 
    { 

     int IComparer.Compare(Object x, Object y) 
     { 
      FileInfo _x = x as FileInfo; 
      FileInfo _y = y as FileInfo; 

      Match m1 = RegExps.ExprFileVersion.Match(_x.FullName); 
      Match m2 = RegExps.ExprFileVersion.Match(_y.FullName); 
      if (m1.Success && m2.Success) // we have versioned files 
      { 

       string n1; 
       string n2; 
       n1 = m1.Groups[2].Value; 
       n2 = m2.Groups[2].Value; 

       string s1 = m1.Groups[1].Value; 
       string s2 = m2.Groups[1].Value; 

       int max = Math.Max(n1.Length, n2.Length); 

       n1 = n1.PadLeft(max, '0'); 
       n2 = n2.PadLeft(max, '0'); 

       if (s1.Equals(s2)) // we have to compare the version 
        // which is now left-padded with 0s. 
       { 
        return ((new CaseInsensitiveComparer()).Compare(n1, n2)); 
       } 
       else // not the same base file name. So the version does not matter. 
       { 
        return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName)); 
       } 
      } 
      else // not versioned 
      { 
       return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName)); 
      } 
     } 
    } 

回答

1

是的,有。這個問題已經回答了here。您基本上想通過P/Invoke層調用StrCmpLogicalW函數。看到原來的答案的全部細節:

Natural Sort Order in C#

+0

我不喜歡的P/Invoke。它總是讓我覺得它是某種黑客;) 謝謝。我會看看它。對我的例外問題有任何想法? – user51710 2009-01-08 20:49:18