У меня есть 7-8 xml файлов. Каждый из них имеет размер приблизительно 50 МБ. Каков наилучший способ слияния файлов программно на C# без получения исключения System.OutOfMemory? До сих пор я пробовал читать каждый файл в StringBuilder и помещать его в массив строковых построителей, но я все равно получаю исключение system.outofmemoery. Любая помощь?? Спасибо, -NimeshСлияние больших файлов в C#
ответ
Лично я, когда есть работать с файлами XML (принудительная под угрозой физического насилия обычно), я делаю это:
- Загрузка каждого файла в .NET DataSet через DataSet.ReadXML()
- Объедините информацию (с помощью запросов DataSet).
- Запиши комбинированную DataSet в XML с помощью DataSet.WriteXML()
Тогда я агрессивно удалить Orginal файл XML и протирать секторы, где он существовал на диске, чтобы удалить скверну. :-)
Дело в том, что вы по-прежнему пытаетесь сохранить все содержимое в памяти. Вы хотите хранить только небольшую порцию в памяти за раз, а это означает использование потоков. Не читайте весь файл в памяти, не открывайте поток на нем и не читайте его из потока.
Проблема с xml заключается в том, что вы не можете просто добавить их друг к другу: вы разложите вложенность тегов. Поэтому вам нужно что-то узнать о структуре ваших xml-файлов, чтобы вы могли иметь представление о том, что делать в каждой файловой границе.
Если у вас есть что-то, что теоретически работает со StringBuilder, но на практике это происходит только из-за ограничений памяти, вы должны иметь возможность переводить методы StringBuilder .Append() и .AppendLine() в .Write() и .WriteLine() вызывает поток.
Это зависит от того, что вы подразумеваете под слиянием, так как вы не разместили никакой информации о схеме.
В простейшем случае однородных простых элементов в одном наборе вы просто просто присоединяетесь к новому файлу на диске, избегая много работы в памяти, гарантируя, что внешние содержащие элементы будут удалены и добавлены вокруг коллекции.
Не уверен, что вы подразумеваете под слиянием в этом случае. Вы имеете в виду простую конкатенацию файлов, или вы проверяете содержимое?
, например,
file1.xml
<items>
<item id="1">
<name>Widget</name>
</item>
<item id="2">
<name>Widget 2</name>
</item>
</items>
file2.xml
<items>
<item id="3">
<name>Widget</name>
</item>
<item id="4">
<name>Widget 2</name>
</item>
</items>
могут быть объединены, как
<items>
<item id="1">
<name>Widget</name>
</item>
<item id="2">
<name>Widget 2</name>
</item>
</items>
<items>
<item id="3">
<name>Widget</name>
</item>
<item id="4">
<name>Widget 2</name>
</item>
</items>
который является довольно тривиальным, или как
<items>
<item id="1">
<name>Widget</name>
</item>
<item id="2">
<name>Widget 2</name>
</item>
<item id="3">
<name>Widget</name>
</item>
<item id="4">
<name>Widget 2</name>
</item>
</items>
Это не так, учитывая количество данных, о которых вы говорите. Что ты имеешь в виду?
Укажите «merge».
Если вы хотите просто конкатенировать файлы, используйте StreamReader и читайте строки за строкой.
Если вы действительно хотите создать новый действительный xml, перейдите к XmlTextReader. Он не читает весь файл в памяти.
Детали того, что вам нужно для слияния, действительно жизненно необходимы. Однако, чтобы начать: вы, скорее всего, захотите XmlReader для каждого из входных файлов и XmlWriter для выходного файла. Это позволит вам передавать как входные, так и выходные данные.
Другой альтернативой может быть использование XStreamingElement из LINQ to XML. У меня нет опыта в этом, но, возможно, это будет более простой API.(Остальная часть LINQ to XML, безусловно, лучше, чем DOM API.)
Объединить их в файловой системе, вызвав команду «copy a.xml + b.xml» или вызывая API-интерфейсы файловой системы Windows, используемые « копировать ".
Без примера того, как вы будете сливаться, довольно сложно дать ответ, как указали некоторые люди. – 2008-09-29 16:26:24
Название этого вопроса должно быть лучше: «Объединение больших XML-файлов в C#», поскольку, например, для слияния двоичных файлов потребуется совершенно другой подход. – Christian 2009-09-17 06:21:41