У меня странная проблема, по которой я не могу найти решение. Я пытаюсь прочитать большие файлы (от 500 МБ до 2 ГБ) кусками 8М строк.File.ReadLines выбрасывает OutOfMemoryException
Для этого я создал следующее:
public static List<string> read_file(string path, Int32 start, Int32 end, Boolean is_big_file)
{
try
{
List<string> lines = new List<string>();
if (is_big_file)
lines = File.ReadLines(path).Skip(start).Take(end - start).ToList();
else
lines = File.ReadAllLines(path).ToList();
return lines;
}
catch { return null; }
}
Если файл имеет меньше 8M линий, ReadAllLines используется, и все работает. Если файл больше, он будет использовать ReadLines.Skip.Take.
Первый кусок работает, я получаю первые 8 M строк. Старт = 0. конец = 8 000 000.
Второй кусок не работает. старт = 8,000,000. end = 16 000 000 или последняя строка файла (в зависимости от количества строк). По какой-то причине я получаю OutOfMemoryException, когда у меня есть менее 8M строк для чтения (end = 12,500,000).
У вас есть идеи, почему это происходит? Пропускает ли кеширует исходные строки? Есть ли более элегантное решение?
Спасибо!
В каждом запросе, читающем любой последующий фрагмент, вы физически читаете все предыдущие строки (куски). Неудивительно, что он ест память, как сумасшедшую. Вам лучше работать с файлом с помощью StreamReader. –
Могу ли я спросить: как вызывающий вызывающий этот метод для большого файла считывает несколько партий? Что удивительно для меня, так как ваш подход может быть чрезвычайно неэффективным **, File.ReadLines возвращает IEnumerable, который внутренне использует StreamReader (то же, что и принятый ответ ниже), чтобы читать по одной строке за раз. Если вы явно не держите большое количество строк в памяти или не делаете что-то еще неправильно, вам должно быть сложно получить исключение OOM (не исключено, хотя .. и опять же, этот подход, безусловно, неэффективен). –
Если вы выполняете пакетную обработку строк только из-за опасений, что у вас есть большой файл для обработки, и все, что вам нужно сделать, это обрабатывать каждую строку один раз, по одной строке за раз, я бы рекомендовал вам сохранить его простым и просто используйте 'IEnumerable', возвращаемый методом ReadLines, для итерации по всем строкам. Все строки не должны загружаться, учитывая, как Iterator реализован с использованием' StreamReader' (нет необходимости повторно изобретать колесо, если я понимаю ваша потребность правильно). См. Http://referencesource.microsoft.com/#mscorlib/system/io/file.cs,d989485a49fbbfd2 –