Изменение файла XML на месте? - PullRequest
4 голосов
/ 13 октября 2011

Предположим, у меня есть следующий XML-файл:

<book>
 <name>sometext</name>
 <name>sometext</name>
 <name>sometext</name>
 <name>Dometext</name>
 <name>sometext</name>
</book> 

Если бы я хотел изменить содержимое, изменив D на s (как показано в четвертом узле «имя») без необходимости чтения / записи всего файла, было бы это возможно?

Ответы [ 4 ]

3 голосов
/ 13 октября 2011

Файл размером 10 МБ не является проблемой. Хлебни это. Изменить DOM. Запишите его обратно в файловую систему. 10 ГБ это больше проблем. В этом случае:

Предположение : Вы не меняете длину файла. Думайте о файле как о массиве символов, а не как о (связанном) списке символов: вы не можете добавлять символы в середине, только изменять их.

Вам нужно seek изменить позицию в файле, а затем write этот символ на диск.

В мире .NET с объектом FileStream вы можете установить атрибут Position для индекса символа D и затем написать один символ s. Проверьте этот вопрос при произвольном доступе к текстовым файлам .

Также прочитайте этот вопрос: Как вставить символы в файл, используя C # . Похоже, вы не можете реально использовать объект FileStream, но вместо этого вам придется прибегать к записи отдельных байтов.

Удачи. Но на самом деле, если мы говорим только 10 МБ, то просто выплескиваем это. Компьютер должен выполнять вашу работу.

2 голосов
/ 13 октября 2011

Я бы просто прочитал файл, обработал и выплюнул его обратно.

Это можно сделать потоковым способом с XmlReader - это больше ручная работа, чем XmlDocument или XDocument, но при этом избегается создание DOM в памяти (XmlDocument / XDocument можно использовать с этим же шаблон чтения / записи, но обычно требует полной реконструкции в памяти):

  1. Открыть файл входного потока файлов (XmlReader)
  2. Открыть поток выходного файла (XmlWriter, в другой файл )
  3. Чтение из XmlReader и запись в XmlWriter, выполняя любые преобразования как необходимые.
  4. Закрыть потоки
  5. Переместить новый файл в старый файл (перезапись, атомарное действие)

Хотя этот можно настроить для обработки ввода и вывода в одном и том же открытом файле с кучей действительно умных работ ничего не будет сохранено, и есть много вариантов, включая увеличение уменьшение длины файла. На самом деле, может быть медленнее пытаться просто сдвинуть содержимое файла назад, чтобы заполнить пробелы, или сдвинуть содержимое файла вперед, чтобы освободить место. Кэш файловой системы, скорее всего, сделает любой «выигрыш» минимальным / спорным для чего угодно, кроме самой основной операции сохранения длины. Кроме того, изменение файла на месте не является атомарным действием и, как правило, невозможно восстановить в случае ошибки: за счет временного файла подход чтения / записи / перемещения является атомарным по отношению к окончательное содержимое файла.

Или рассмотрим XSLT - он был разработан для этого; -)

Счастливого кодирования.

1 голос
/ 13 октября 2011

XML-файл является текстовым файлом и не позволяет вставлять / удалять.Поддерживаются только мутации OverWrite и Append.Не очень подходит для XML.

Итак, сначала убедитесь, что это действительно нужно.Это сложная операция, которая стоит только для очень больших файлов.

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

Проще скопировать весь файл.Это дорого в I / O, но вы экономите на использовании памяти.

1 голос
/ 13 октября 2011

Самый чистый (и лучший) способ - использовать объект XmlDocument для манипуляции, но быстрое и грязное решение - просто прочитать XML в строку и затем:

xmlText = xmlText.Replace("Dometext", "sometext");
...