使用C#处理大型文本文件

5

我有4GB以上的文本文件(csv格式),我想使用C#中的linq处理此文件。

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

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

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

谢谢


你使用的是哪个版本的.NET? - Rune FS
3个回答

12

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

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

[编辑]

如果您需要对文件中的数据运行复杂查询,正确的做法是将数据加载到数据库中,让数据库管理系统处理数据检索和内存管理。


1
如果所有文本都在一行内且没有回车符,怎么办? - Rosmarine Popcorn
1
@Cody - 我假设csv文件不是单行文件。 - Alex Aza
2
那么你将会把整行作为字节流来处理,而不是一行一行地处理。 - Roy Dictus
我应该将所有数据加载到内存中以运行Linq查询并创建新结果吗? - oguzh4n
我运行了一个复杂的LINQ查询(自连接和另一个谓词)。 - oguzh4n
显示剩余3条评论

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;
                }
            }
        }

谢谢建议,我尝试了这个解决方案,但它非常慢,并且有相同的内存问题。 - oguzh4n
@oguzh4n 哦,我故意没有考虑速度,因为你在帖子中没有提到。在任何情况下,我更喜欢可读性(在调用站点的情况下)。关于内存问题。如果您能更精确地描述它们,它们可以被修复。这不必一次保存超过文本文件的一行和一个黏土对象(以及一点点),因此上面的草稿所具有的任何内存问题都可以被修复。 - Rune FS

1

我认为这是一个不错的方法... CSV


问题是这样的,需要读取500MB的字节数据,但内存只有2GB。 - oguzh4n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接