Почему ReadAllLines работает в WPF, а не в ConsoleApp
Я делаю несколько тестов на различные способы чтения файла CSV и обнаружил "странную" проблему. Проблема в том, что когда я использую этот метод в консольном приложении:
var lines = File.ReadAllLines(fileName); // OutOfMemoryException
foreach (var line in lines)
{
//doing stuff
}
Я получаю OutOfMemoryException, но когда я использую тот же метод в моем проекте WPF, он работает нормально. Файл, на котором я тестирую этот файл, составляет 730 МБ, и я знаю, что не следует использовать ReadAllLines для больших файлов CSV, но почему этот метод работает в приложении WPF, а не в консольном приложении?
3 ответа
Вы используете 32-битный процесс и страдаете от фрагментации адресного пространства. Это означает, что среда выполнения не может выделить достаточно непрерывной памяти, хотя в целом достаточно памяти будет свободно. WPF может иметь тенденцию иметь лучшую разметку памяти.
Измените проект на 64-битный.
Или потоковое файл с помощью File.ReadLines
,
Я подозреваю, что ваше приложение WPF скомпилировано на любом процессоре, а ваше консольное приложение на целевом процессоре x32. Если вы запускаете приложения на компьютере с архитектурой x64, приложение WPF может использовать гораздо больше памяти по сравнению с консольным приложением с архитектурой x32, которое ограничено примерно 1,5 ГБ.
Кроме того, я предлагаю изменить ваш подход и, если возможно, не обрабатывать весь файл сразу.
Я не буду давать вам прямой ответ на ваш вопрос, но я думаю, что важно отметить, что OutOfMemoryException
часто указывает на то, что ваша программа слишком сильно нагружает память или не очень хорошо использует доступные ресурсы.
В вашем случае вы эффективно кэшируете весь файл в памяти, вызывая File.ReadAllLines
, Однако это может быть вовсе не нужно, потому что сразу после этого вы будете обрабатывать его построчно. То есть может быть достаточно иметь в памяти только одну строку текста:
Как говорится в этом ответе, вы можете использовать
File.ReadLines
Поток файла построчно.Если вы ориентируетесь на версию.NET Framework более раннюю, чем.NET 4, этот метод будет недоступен. Вы можете заменить его своей собственной реализацией, например:
// using System.IO; static IEnumerable<string> ReadLines(string filePath) { using (var input = File.OpenText(filePath)) { while (!input.EndOfStream) { string line = input.ReadLine(); yield return line; } } }