在C#中处理大型文本文件

时间:2011-06-24 07:18:00

标签: c# .net string c#-4.0 .net-4.0

我有4GB +文本文件(csv格式),我想在c#中使用linq处理这个文件。

我在加载csv后运行复杂的linq查询并转换为类?

但文件大小为4gb,尽管应用程序内存是文件的双倍大小。

我如何处理(linq和新结果)大文件?

由于

3 个答案:

答案 0 :(得分:11)

您可以逐行读取和处理文件,而不是将整个文件加载到内存中。

using (var streamReader = new StreamReader(fileName))
{
    string line;
    while ((line = streamReader.ReadLine()) != null)
    {
        // analize line here
        // throw it away if it does not match
    }
}

<强> [编辑]

如果您需要针对文件中的数据运行复杂查询,那么正确的做法是将数据加载到数据库并让DBMS负责数据检索和内存管理。

答案 1 :(得分:1)

我觉得这个好方法...... CSV

答案 2 :(得分:1)

如果您使用的是.NET 4.0,则可以使用Clay,然后编写一个返回行的IEnumerable行的方法,并使代码如下所示

from record in GetRecords("myFile.csv",new []{"Foo","Bar"},new[]{","})
where record.Foo == "Baz"
select new {MyRealBar = int.Parse(record.Bar)

将CSV投影到一系列Clay对象的方法可以创建如下:

 private IEnumerable<dynamic> GetRecords(
                    string filePath,
                    IEnumerable<string> columnNames, 
                    string[] delimiter){
            if (!File.Exists(filePath))
                yield break;
            var columns = columnNames.ToArray();
            dynamic New = new ClayFactory();
            using (var streamReader = new StreamReader(filePath)){
                var columnLength = columns.Length;
                string line;
                while ((line = streamReader.ReadLine()) != null){
                    var record = New.Record();
                    var fields = line.Split(delimiter, StringSplitOptions.None);
                    if(fields.Length != columnLength)
                        throw new InvalidOperationException(
                                 "fields count does not match column count");
                    for(int i = 0;i<columnLength;i++){
                        record[columns[i]] = fields[i];
                    }
                    yield return record;
                }
            }
        }