2013-02-26 152 views
4

我對c#編程非常陌生,所以如果我的問題微不足道,我很抱歉。 我運行一些C#代碼,我需要遍歷文件夾中的一些文件和正在使用:按特定順序遍歷文件夾中的文件?

foreach (string f in Directory.GetFiles(@"C:\temp\GeneralStats")) 
{ 

不過,我想有這些文件,根據文件名中的一個特定的順序讀取。我的文件名是下面的格式。

 
generalstats_2012_11_1.csv 
generalstats_2012_11_2.csv 
generalstats_2012_11_3.csv 
..... 

當我的代碼,它與generalstats_2012_11_1.csv啓動文件中讀取,但然後跳轉直接generalstats_2012_11_10.csv,而不是generalstats_2012_11_2.csv。

我已經嘗試在網上尋找答案,但一直無法找到任何答案。我當然按照特定文件夾中的日期(在名稱中)排序文件,但代碼根本不承認。 任何人都可以幫助我 - 是否有一些順序功能在C#,我錯過了?

+0

搜索'人sort'或'自然排序order' – abatishchev 2013-02-26 08:20:29

+0

使用兩位數字的月份和日子!或者玩得開心實施[自然排序](http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting) – alldayremix 2013-02-26 08:27:52

+0

[自然排序順序在C#中](http: //stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp)。(這個問題不是很好,但最重要的答案應該是針對你的解決方案 - 它基本上顯示瞭如何使用與Windows相同的底層函數來排序文件。) – Rawling 2013-02-26 08:31:51

回答

2

您可以使用此:

 var paths = Directory.GetFiles(@"C:\temp\GeneralStats") 
      .OrderBy(path => 
       Convert.ToInt32(path.Split('_', '.')[1]) * 10000 + 
       Convert.ToInt32(path.Split('_', '.')[2]) * 100 + 
       Convert.ToInt32(path.Split('_', '.')[3])); 

     foreach (string path in paths) 
     { 
     } 

這從文件名獲取日期部分,並創造出他們的整數,例如2012_11_10從文件的名稱是2012110的整數,2012_11_1是20121101等。這些數字用於分類。

上述方法的另一個變體是:

 var paths = Directory.GetFiles(@"C:\temp\GeneralStats") 
      .OrderBy(path => 
       Convert.ToInt32(
        String.Concat(
         path.Split('_', '.') 
          .Skip(1) 
          .Take(3) 
          .Select(num => num.PadLeft(2, '0')) 
          .ToArray()) 
       ) 
      ); 

它還從文件名解析數,並創建用於排序的整數。

代替Directory.GetFiles方法,您可以使用Directory.EnumerateFiles(但僅適用於.NET 4及更高版本)。

+0

第二個想法是否正確處理2012_1_11與2012_11_1? – 2013-02-26 08:42:08

+0

@KierenJohnstone我不認爲它是這樣,這就是爲什麼我刪除它:)感謝注意它。 – 2013-02-26 08:48:48

+0

它完美的工作 - 非常感謝你,我感謝它伊萬G – 2013-02-26 08:52:59

2

如果您想按文件名後面的日期排序,您必須將其轉換爲一個,否則順序按字母順序排列(因此「10」位於「2」之前)。

您可以在此LINQ查詢使用Enumerable.OrderBy

var files = Directory.EnumerateFiles(@"C:\temp\GeneralStats", "*.csv") 
    .Select(fn => new 
    { 
     Path = fn, 
     Split = Path.GetFileNameWithoutExtension(fn).Split('_') 
    }) 
    .Where(x => x.Split.Length == 4) 
    .Select(x => new 
    { 
     x.Path, 
     Date = new DateTime(int.Parse(x.Split[1]), int.Parse(x.Split[2]), int.Parse(x.Split[3])) 
    }) 
    .OrderBy(x => x.Date) 
    .Select(x => x.Path); 

首先,我選擇匿名類型從Path類像GetFileNameWithoutExtension一些有用的特性。這將使查詢的其餘部分更有效並且更具可讀性。 Where用於防止在文件名中沒有日期部分的文件時發生錯誤。下一個選擇解析來自string.Split的令牌的DateTime。最後三部分包含年,月和日。 OrderBy將按日期排序。最後,我再次選擇完整路徑,因爲您最初想要訂​​購這些文件。

您可以用foreach來列舉結果或使用例如ToList,如果你想堅持的:

foreach (string f in files) 
{ 
    // ... 
} 
+0

謝謝,我真的很感激 - 我無法完成這項工作,但Ivan G的下面答案爲我解決了這個問題。 – 2013-02-26 08:51:40

+0

@LeneJungKjær:也許你在使用.NET 3.5,'EnumerateFiles'需要.NET框架4,然後簡單地用'GetFiles'替換它,它將所有文件首先讀入內存。其餘的工作也在3.5。 – 2013-02-26 08:53:21

+0

好的,感謝info @TimSchmelter並感謝您的幫助。 – 2013-02-26 09:49:40