【发布时间】:2011-06-24 07:18:00
【问题描述】:
我有 4GB 以上的文本文件(csv 格式),我想在 c# 中使用 linq 处理这个文件。
我在加载 csv 并转换为类后运行复杂的 linq 查询?
但文件大小为 4gb,尽管应用程序内存是文件大小的两倍。
如何处理(linq 和新结果)大文件?
谢谢
【问题讨论】:
-
你使用的是什么版本的 .NET
标签: c# .net string c#-4.0 .net-4.0
我有 4GB 以上的文本文件(csv 格式),我想在 c# 中使用 linq 处理这个文件。
我在加载 csv 并转换为类后运行复杂的 linq 查询?
但文件大小为 4gb,尽管应用程序内存是文件大小的两倍。
如何处理(linq 和新结果)大文件?
谢谢
【问题讨论】:
标签: c# .net string c#-4.0 .net-4.0
您可以逐行读取和处理文件,而不是将整个文件加载到内存中。
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 负责数据检索和内存管理。
【讨论】:
如果您使用的是 .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;
}
}
}
【讨论】: