Прочитайте сжатый XML с .NET - PullRequest
       32

Прочитайте сжатый XML с .NET

2 голосов
/ 11 января 2010

Случай: существует большой zml-файл в формате zip, который должен быть проанализирован программой .NET. Основной проблемой является слишком большой размер файла, поэтому он не может быть полностью загружен в память и разархивирован.

Файл необходимо читать по частям таким образом, чтобы после распаковки этих частей они были «согласованными». Если часть содержит только половину узла, ее невозможно будет проанализировать ни в одной xml-структуре.

Буду признателен за любую помощь. :)

Редактировать: текущее решение извлекает весь zip-файл по частям и записывает его в виде XML-файла на диск. Затем читает и анализирует XML. Нет лучших идей так далеко от моего сайта:).

Ответы [ 5 ]

4 голосов
/ 11 января 2010

Используя DotNetZip, вы можете сделать это:

using (var zip = ZipFile.Read("c:\\data\\zipfile.zip"))
{
    using (Stream s = zip["NameOfXmlFile.xml"].OpenReader())
    {
        // Create the XmlReader object.
        using (XmlReader reader = XmlReader.Create(s))
        {
            while (reader.Read()) 
            {
                ....
            }
        }
    }
}
1 голос
/ 11 января 2010

Вы можете попробовать SharpZipLib, а затем использовать XmlReader, чтобы начать его синтаксический анализ.

1 голос
/ 11 января 2010

Разве вы не пробовали Библиотека DotNetZip (нажмите на эту ссылку) ?

В ответ на ваше недавнее издание ::
То, что вы делаете, является стандартом поток / путь ..
Насколько мне известно альтернативы этому нет.

0 голосов
/ 11 января 2010

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

Это означает, что вам придется использовать потоки, которые собираются именно для этого случая. Это решение будет работать, но оно может быть ограничено в зависимости от того, что вы надеетесь сделать с данными XML. Вы говорите, что он должен быть проанализирован, но единственный способ, которым вы сможете это сделать (поскольку вы не можете сохранить его в памяти), - это иметь возможность прочитать его «способом пожарного шланга», проходя через каждый узел, так как он анализируется , Надеюсь, этого достаточно, чтобы иметь возможность извлекать те данные, которые вам нужны, или обрабатывать их так, как вам нужно (засовывать их в БД, извлекать только те разделы, в которые вы инте- стируются, и сохранять их в меньшем по объему XML-документе в памяти? И т. Д.)

Итак, первая работа, получить поток из вашего zip-файла, довольно легко сделать с SharpZipLib (+1 к Рубенсу). Добавьте ссылку на dll SharpZipLib в свой проект. Вот некоторый код, который создает поток из zip-файла и затем добавляет его в поток памяти (вы, возможно, не захотите делать этот бит, но он показывает вам, как я использую его для возврата байта [] данных, вам просто нужен поток ):

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Diagnostics;
using System.Xml;

namespace Offroadcode.Compression
{
    /// <summary>
    /// Number of handy zip functions for compressing/decompressing zip data.
    /// </summary>
    public class Zip
    {

        /// <summary>
        /// Decompresses a btye array of previously compress data from the Compress method or any Zip program for that matter.
        /// </summary>
        /// <param name="bytes">Compress data as a byte array</param>
        /// <returns>byte array of uncompress data</returns>
        public static byte[] Decompress( byte[] bytes ) 
        {
            Debug.Write( "Decompressing byte array of size: " + bytes.Length  );

            using( ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream stream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream( new MemoryStream( bytes ) ) ) 
            {
                                // Left this bit in to show you how I can read from the "stream" and save the data to another stream "mem"
                using ( MemoryStream mem = new MemoryStream() ) 
                {
                    int size = 0;
                    while( true ) 
                    {
                        byte[] buffer = new byte[4096];
                        size = stream.Read( buffer, 0, buffer.Length );

                        if ( size > 0 ) 
                        {
                            mem.Write( buffer, 0, size );
                        }
                        else
                        {
                            break;
                        }
                    }

                    bytes = mem.ToArray();
                }
            }

            Debug.Write( "Complete, decompressed size: " + bytes.Length );

            return bytes;
        }

Тогда, если вы будете следовать этой статье: http://support.microsoft.com/kb/301228 от MS, вы сможете объединить две партии кода и начать читать ваш XML из потока zip:)

0 голосов
/ 11 января 2010

Относительно вашего редактирования: Если вы на самом деле не хотите иметь этот XML-файл на диске (что, конечно, может иметь место в некоторых сценариях), я бы извлек его в MemoryStream вместо этого.

...