2015-04-10 3 views
0

У меня есть код для синтаксического анализа текстового файла после выполнения переформатирования.Реформат и разбор огромного текстового файла в C#

foreach (string file in Directory.EnumerateFiles(folderPath, "*.*")) 
{ 
    contents = contents + File.ReadAllText(file).Replace("&gt;", ">").Replace("&lt;", "<").Replace("&quot;", "'"); 
    pos = contents.LastIndexOf("</event>"); 
    contents = contents.Substring(0, pos + 8); 
} 

contents = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root>" + contents + "</root>"; 

XDocument doc = new XDocument(); 
doc = XDocument.Parse(contents); 

Файл содержит теги XML, но не отформатирован должным образом. Следовательно, я переформатирую и сохраняю в строковой переменной contents. Эта строка загружается в объект XDocument, и программа работает плавно для небольших файлов (7-10 МБ).

Теперь есть файлы, которые более 100MB в размерах и разрывы кода с из памяти exception.My разрывов кода на

contents = contents + File.ReadAllText(file).Replace("&gt;", ">").Replace("&lt;", "<").Replace("&quot;", "'"); 

Какие альтернативы у меня есть, чтобы сделать ту же операцию с эффективным файлом обработки.

+3

Один из них становится любопытным - если файл имеет размер более 100 МБ, действительно ли он * действительно * должен быть общедоступным для чтения? –

+0

В вашем текущем коде каждый 'Replace' вызывает другое распределение строк в уже огромной строке в памяти. Не удивительно, что у вас закончилась нехватка памяти. Используйте потоки ('StreamReader') и обрабатывайте куски. – Alex

ответ

1

Вы не сможете работать с файлами более 100 МБ с помощью XDocument, поскольку он хранит все в памяти и выполняет все операции в памяти. Для этого используйте XmlReader.

+0

Да. Хотя ваш код синтаксического анализа может использовать некоторое повышение производительности, маловероятно, что он вызывает проблему с неполадкой. Это действительно использование XDocument, которое нечувствительно к памяти и, следовательно, вызывает вашу проблему. Если вы не хотите иметь дело с XmlReader (это довольно низкоуровневый), проверьте XStreamingElement (https://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement(v=vs. 110) .aspx и https://msdn.microsoft.com/en-us/library/bb387013.aspx) – ofcoursedude

+0

У меня была такая же проблема с большими файлами, и после переключения на XmlReader сокращение потребления памяти может быть примерно в 10 раз это хорошее решение. – demonplus

+0

мой код разбивается на содержимое = содержимое + File.ReadAllText (файл) .Replace («>», «>»). Заменить («<», «<»).Заменить («"», «'»); – mhn

2

Как уже указывалось, ключ заключается в использовании потоковой передачи вместо полных операций с оперативной памятью.

Вы можете создать собственный TextReader подкласс FormattingReader, который оборачивает StreamReader или подобное и выполняет свой процесс форматирования на лету во время чтения:

  • Вывод XML заголовка
  • Выход открытие <root> тег
  • Итерации над вашими файлами:
    • Когда вы видите &lt; или &gt; на обернутом re Адер, выходные угловые скобки вместо
    • Когда вы видите </event> тег, рассматривать его как конец файла
  • Выход закрытия </root>

Затем используйте XmlReader.Create() перегрузку, которая принимает TextReader и передать экземпляр вашего FormattingReader.

+0

Извините, я пропустил, что вы используете 'LastIndexOf', чтобы найти тег' 'для пропуска. Таким образом, описание моего алгоритма не подходит, и идея может не помочь; это зависит от того, сколько вы должны сделать, чтобы определить, вы только что видели последний ''. Я не удаляю его, потому что он все еще может дать вам еще один вариант попробовать. – nodots

Смежные вопросы