Разделение большого XML-файла на две части с помощью консольного приложения C # - PullRequest
1 голос
/ 22 сентября 2011

Мне нужно разделить файл XML (~ 400 МБ) на две части, чтобы устаревшее приложение могло обработать файл. В настоящий момент создается исключение, когда размер файла превышает 300 МБ.

Поскольку я не могу изменить приложение, которое выполняет обработку, я подумал, что смогу написать консольное приложение, чтобы сначала разбить файл на две части. Какой лучший способ сделать это? Это должно быть автоматизировано, поэтому я не могу использовать текстовый редактор, и я использую C #.

Полагаю, следующие соображения:

  • запись заголовка для новых файлов после разделения
  • найти хорошее место для разделения (не в середине 'объекта')
  • правильно закрывает теги и файл в первом файле, правильно открывает теги во втором файле

Есть предложения?

Ответы [ 3 ]

2 голосов
/ 22 сентября 2011

Возможно, вы захотите сделать полную копию файла, а затем удалить элементы из каждого. Вам придется решить, на каком уровне могут происходить удаления.

После подсчета количества элементов, удаленных из FileA, должно быть достаточно просто определить, сколько (и из какой начальной точки) следует удалить из FileB.

Это возможно для ваших обстоятельств?

Я собрал следующее, чтобы описать свое мышление. Это не проверено, но я бы оценил комментарии группы. Проголосуй, если хочешь, но я бы предпочел конструктивную критику.

using System.Xml;
using System.Xml.Schema;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            SplitXML(args[0], args[1]);
        }

        private static void SplitXML(string fileNameA, string fileNameB)
        {
            int deleteCount;
            XmlNodeList childNodes;
            XmlReader reader;
            XmlTextWriter writer;
            XmlDocument doc;

            // ------------- Process FileA
            reader = XmlReader.Create(fileNameA);
            doc = new XmlDocument();
            doc.Load(reader);

            childNodes = doc.DocumentElement.ChildNodes;
            deleteCount = childNodes.Count / 2;

            for (int i = 0; i < deleteCount; i++)
            {
                doc.DocumentElement.RemoveChild(childNodes.Item(0));
            }
            writer = new XmlTextWriter("FileC", null);
            doc.Save(writer);

            // ------------- Process FileB
            reader = XmlReader.Create(fileNameB);
            doc = new XmlDocument();
            doc.Load(reader);

            childNodes = doc.DocumentElement.ChildNodes;

            for (int i = deleteCount + 1; i < childNodes.Count; i++)
            {
                doc.DocumentElement.RemoveChild(childNodes.Item(deleteCount +1));
            }
            writer = new XmlTextWriter("FileD", null);
            doc.Save(writer);

        }
    }
}
2 голосов
/ 22 сентября 2011

«Лучший» способ, вероятно, будет основан на XmlReader и XmlWriter. Использование этих «потоковых» API избавляет от необходимости загружать всю объектную модель XML в память (и с DOM - XmlDocument - которая может потребовать значительно больше памяти, чем текстовые данные).

Использовать эти API сложнее, чем просто загрузить документ: ваша реализация должна отслеживать контекст (например, текущий узел и список предков), но в этом случае это не будет сложно (достаточно просто открыть элементы для текущее состояние при открытии каждого выходного документа).

0 голосов
/ 22 сентября 2011

Если это чистый C #, запуск его как 64-битного процесса может решить проблему без каких-либо усилий (при условии, что у вас под рукой 64-битная Windows).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...