Обработка большого текстового файла в C # - PullRequest
5 голосов
/ 24 июня 2011

У меня есть 4 ГБ + текстовые файлы (формат csv), и я хочу обработать этот файл, используя linq в c #.

Я запускаю сложный запрос linq после загрузки csv и конвертирую в класс?размер файла составляет 4 ГБ, хотя память приложения в два раза больше файла.

как я могу обрабатывать (linq и новый результат) большие файлы?

Спасибо

Ответы [ 3 ]

11 голосов
/ 24 июня 2011

Вместо загрузки всего файла в память, вы можете читать и обрабатывать файл построчно.

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

[EDIT]

Если вам нужно выполнить сложные запросы к данным в файле, правильная вещь - это загрузить данные в базу данных и позволить СУБД позаботиться о получении данных и управлении памятью.

1 голос
/ 24 июня 2011

Если вы используете .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;
                }
            }
        }
1 голос
/ 24 июня 2011

Я думаю, что это хороший способ ... CSV

...