c # Как читать один файл с обычными и текстовыми элементами XML - PullRequest
3 голосов
/ 15 апреля 2011

Я получаю поток данных от веб-службы и пытаюсь сохранить содержимое потока в файл.Поток содержит стандартные строки текста вместе с большими кусками XML-данных (в одну строку).Размер файла составляет около 800 МБ.

Проблема: Получение исключения из нехватки памяти при обработке раздела xml каждой строки.

==start file
line 1
line 2
<?xml version=.....huge line etc</xml>
line 3
line4
<?xml version=.....huge line etc</xml>
==end file

Текущий код, как вы можете видеть, когда он читает в огромной строке xml, он переполняет память.

string readLine;
using (StreamReader reader = new StreamReader(downloadStream))
{
    while ((readLine = reader.ReadLine()) != null)
    {
        streamWriter.WriteLien(readLine); //writes to file
    }
}

Я пытался найти решение, в котором для обработки я использовал одновременно TextReader / StreamReader и XmlTextReaderкаждый раздел.Добравшись до раздела xml, я мог переключиться на XmlTextReader и использовать метод Read () для чтения каждого узла, тем самым останавливая скачок памяти.

Есть предложения о том, как я могу это сделать?В качестве альтернативы, я мог бы создать собственный XmlTextReader, который мог читать в этих строках?Любые указатели для этого?

Обновлено

Еще одна проблема заключается в том, что мне нужно прочитать этот файл обратно и разделить две секции XML для отдельных файлов XML!Я преобразовал решение для записи файла с использованием бинарного устройства записи, а затем начал считывать файл обратно с помощью бинарного устройства чтения.У меня есть обработка текста, чтобы определить начало раздела XML и, в частности, какой раздел XML, чтобы я мог сопоставить его с правильным файлом!Однако это вызывает проблемы с чтением в двоичном файле и обнаружением ...

using (BinaryReader reader = new BinaryReader(savedFileStream))
{
    while ((streamLine = reader.ReadString()) != null)
    {
        if (streamLine.StartsWith("<?xml version=\"1.0\" ?><tag1"))
        //xml file 1
        else if (streamLine.StartsWith("<?xml version=\"1.0\" ?><tag2"))
        //xml file 2

Ответы [ 3 ]

2 голосов
/ 15 апреля 2011

XML может содержать все содержимое одной строкой, поэтому вам, вероятно, лучше использовать двоичное устройство чтения / записи, где вы можете выбрать размер чтения / записи.

Пример ниже, здесь мы читаем байты BUFFER_SIZE для каждой итерации:

        Stream s = new MemoryStream();
        Stream outputStream = new MemoryStream();
        int BUFFER_SIZE = 1024;
        using (BinaryReader reader = new BinaryReader(s))
        {
            BinaryWriter writer = new BinaryWriter(outputStream);
            byte[] buffer = new byte[BUFFER_SIZE];
            int read = buffer.Length;
            while(read != 0)
            {
                read = reader.Read(buffer, 0, BUFFER_SIZE);

                writer.Write(buffer, 0, read);

            }

            writer.Flush();
            writer.Close();
        }

Я не знаю, вызывает ли это у вас проблемы с кодировками и т. Д., Но я думаю, что вам придется читать файл как двоичный файл.

1 голос
/ 15 апреля 2011

Если все, что вы хотите сделать, это скопировать один поток в другой без изменения данных, вам не нужны текстовые или двоичные помощники Stream (StreamReader, StreamWriter, BinaryReader, BinaryWriter и т. Д.), Просто скопируйте поток.

internal static class StreamExtensions
{
    public static void CopyTo(this Stream readStream, Stream writeStream)
    {
        byte[] buffer = new byte[4096];
        int read;
        while ((read = readStream.Read(buffer, 0, buffer.Length)) > 0)
            writeStream.Write(buffer, 0, read);
    }
}
0 голосов
/ 15 апреля 2011

Я думаю, что есть утечка памяти

Вы получаете исключение из памяти после обработки нескольких строк или самой первой строки?
И в потоке while нет функции streamWriter.Flush ().
Тебе не кажется, что он должен быть?

...