2013-07-18 66 views
3

我有一個函數讀取一個csv文件並返回操作(LINQ)結果。我需要打開每個文件兩次,因爲我需要根據不同的用途對數據進行非常不同的分割,並且使用代碼項目中的「快速CSV閱讀器」,我使用它的速度更快,可以兩次讀取,並且每次直接使用LINQ進行操作比將其讀入DataTable中。與LINQ並行csv處理

單獨的每個函數調用(imppow或impfuel)都需要超過2秒。

簡單的for循環六個電話(需要13secs):

string[] pathstring = { @"C:\Temp\Hourly1.txt", @"C:\Temp\Hourly2.txt", @"C:\Temp\Hourly3.txt" }; 
string[] pathgran = { "M", "Q", "Y" }; 
for (int i=0; i < 3; i++) 
{ 
    var respow = imppow(pathstring[i], pathgran[i]); 
    Console.WriteLine(respow[0]); 

    var resfuel = impfuel(pathstring[i], pathgran[i]); 
    Console.WriteLine(resfuel[0]); 
} 

並行化這樣刮鬍子了3秒,但不多:

Parallel.For(0, 3, (i) => 
{ 
    var respow = imppow(pathstring[i], pathgran[i]); 
    Console.WriteLine(respow[0]); 

    var resfuel = impfuel(pathstring[i], pathgran[i]); 
    Console.WriteLine(resfuel[0]); 
}); 

至於說一個呼叫大約需要2秒。我可以通過使用多線程還是進一步降低runtim? 謝謝。

下面的功能之一:

static object[] impfuel(string filepath, string gran) 
{ 
    using (CsvReader csv = 
      new CsvReader(new StreamReader(filepath), true)) 
    { 
     csv.SupportsMultiline = false; 
     var results = csv.Select(r => new { yr = r[1], qr = r[3], mt = r[4], tar = r[7], mac = r[8], fuel = r[9], rg = r[10], rt = r[11], fp = r[22], fi = r[24] }) 
         .Where(a => a.rt == "F") 
         .GroupBy(a => new { a.rg, a.fuel, a.tar, a.mt }) 
         .Select(g => new { Rpg = g.Select(a => a.rg).First(), Fue = g.Select(a => a.fuel).First(), Tari = g.Select(a => a.tar).First(), Mon = g.Select(a => a.mt).First(), AverageA = g.Average(a => double.Parse(a.fp)), SumA = g.Sum(a => double.Parse(a.fi)) }) 
         .ToArray(); 
     return results; 
    } 
} 

static object[] imppow(string filepath, string gran) 
{ 
using (CsvReader csv = 
     new CsvReader(new StreamReader(filepath), true)) 
{ 
    csv.SupportsMultiline = false; 
    var results = csv.Select(r => new { yr = r[1], qr = r[3], mt = r[4], tar = r[7], mac = r[8], rg = r[10], rt = r[11], pp = r[17], pi = r[19] }) 
        .Where(a => a.rt == "M") 
        .GroupBy(a => new { a.rg, a.tar, a.mt }) 
        .Select(g => new { Rpg = g.Select(a => a.rg).First(), Tari = g.Select(a => a.tar).First(), Mon = g.Select(a => a.mt).First(), AverageA = g.Average(a => double.Parse(a.pp)), SumA = g.Sum(a => double.Parse(a.pi)) }) 
        .ToArray(); 
    return results; 
} 

}

+0

你可以將文件緩存在內存中並使用MemoryStreams嗎?消除文件I/O可能會有所幫助。 –

+2

Parallel.For()使用多個線程(如有必要並且可用) – EkoostikMartin

+0

感謝Dan!你有鏈接或樣本?從來沒有使用記憶流 – nik

回答

2

你永遠不知道這些文件的大小,它是一個幾KB或者在我們談話兆? 一次讀取文件會限制IO速度慢。

我會在閱讀文件時閱讀文件,並將其放入兩個不同的列表中。

string[] pathstring = { @"C:\Temp\Hourly1.txt", @"C:\Temp\Hourly2.txt", @"C:\Temp\Hourly3.txt" }; 
for (int i=0; i < 3; i++) 
{ 
    List<Content> powList = new List<Content>(); 
    List<Content> fuelList = new List<Content>(); 
    ReadFile(pathstring[i], ref powList, ref fuelList); 
    var respow = imppow(powList); 
    Console.WriteLine(respow[0]); 

    var resfuel = impfuel(fuelList); 
    Console.WriteLine(resfuel[0]); 
} 

void ReadFile(string filepath, ref List<Content> powList, ref List<Content> fuelList) 
{ 
    using (CsvReader csv = new CsvReader(new StreamReader(filepath), true)) 
    { 
     csv.SupportsMultiline = false; 
     foreach(Content content in csv.Select(r => new Content(){ yr = r[1], qr = r[3], mt = r[4], tar = r[7], mac = r[8], fuel = r[9], rg = r[10], rt = r[11], pp = r[17], pi = r[19], fp = r[22], fi = r[24] })) 
     { 
      if (content.rt == "F") 
       fuelList.Add(content); 
      else if (content.rt = "M") 
       powList.Add(content); 
     } 
    } 
} 

static object[] impfuel(List<Content> fuelList) 
{ 
    var results = fuelList.GroupBy(a => new { a.rg, a.fuel, a.tar, a.mt }) 
        .Select(g => new { Rpg = g.Select(a => a.rg).First(), Fue = g.Select(a => a.fuel).First(), Tari = g.Select(a => a.tar).First(), Mon = g.Select(a => a.mt).First(), AverageA = g.Average(a => double.Parse(a.fp)), SumA = g.Sum(a => double.Parse(a.fi)) }) 
        .ToArray(); 
    return results; 
} 

}

您可以imppow和內容類你的自我。

+0

thanks for答案。對不起,我應該提到:1個文件是60megs,我們正在說500,000行和26列。我會嘗試你的回答,看看它的速度如何。 – nik

+0

如果你想使它成爲多線程的,你可以使用ReadFile並行運行impfuel和imppow,例如。異步和等待(搜索SO如何做到這一點的例子。) – Casperah

+0

@casperah:謝謝!這工作,並把它下降了另一秒鐘,所以我開始與12-13secs,我的閱讀文件並行6次是8,你的方法將它存儲到兩個列表將其降低到7.我會盡量包括異步和等待現在看看是否會刮掉另一秒... – nik