2013-08-16 1 views
0

Хорошо, только чтобы быть ясным, я знаю обо всех делах LOH и большом объекте (более 85 КБ) и большом списке (более 40 тыс. Элементов), который попадает в LOH.Получите сериализованный размер списка без исключения OutOfMemoryException

Так что моя проблема в том, мне нужно знать размер списка при сериализовать с помощью XMLSerialiser (я не заботиться о пространстве, которое требуется в памяти или что-нибудь подобное, я просто хочу его размер когда сериализованная), но если я пытаюсь сериализация большой список, содержащий большие элементы, которые я получаю OutOfMemoryException (и я знаю, почему)

то, что я хочу знать: можно ли сериализация списка поэлементно и кумуляция его размера в петле, подобной: // Это будет псевдокод

long byteLength = 0; 
using(stream) 
{ 
    foreach(element in MyList) 
    { 
    MemoryStream.Serialise(element); 
    byteLength += MemoryStream.Length; 

    MemoryStream.Clear(); 
    } 
} 

Любое предложение?


UPDATE: Решение по @xanatos делать то, что я хочу сделать, потому что он не добавляет в оперативной памяти большой байт [], который будет храниться в LOH

Как @Hans Passant сказал , мне кажется, что цель ПОЧЕМУ я хочу сделать это лечение, так важно: я хочу знать размер в байте списка, сериализованного в XML, чтобы иметь возможность разбить список на несколько файлов на диске в соответствии с его общим байтом.

+0

Да, но кажется, что даже если я сериализую объекты в своем потоке, длина и позиция не имеют хороших значений ... Я кумулировал «MemoryStream.Length» и переписывал ' Position' to 0 с функцией 'Seek (0,0)' – RPDeshaies

+1

Вы должны быть довольно отчаянным, чтобы написать такой код, конечно, есть лучший подход. Начиная с нескольких объектов и получая оценку, умножая ее на количество Count. Довольно неясно, какая проблема вы * действительно * пытаетесь решить, большие сериализованные данные хорошо подходят на диске, а не в памяти. –

+0

Я думаю, что моя проблема ясна, контекст неясен, потому что это необязательно. Моя проблема: я хочу сериализовать список , не имея все байтов, сериализованных в моем LOH. Решение, отправленное @xanatos, исправить, потому что оно не создает большой 'byte []', а только получает 'Length' из него – RPDeshaies

ответ

2

Если то, что вам нужно, это только длина:

class NulStream : Stream 
{ 
    public override bool CanRead 
    { 
     get { return false; } 
    } 

    public override bool CanSeek 
    { 
     get { return false; } 
    } 

    public override bool CanWrite 
    { 
     get { return true; } 
    } 

    public override void Flush() 
    { 
    } 

    protected long length; 

    public override long Length 
    { 
     get { return this.length; } 
    } 

    public override long Position 
    { 
     get 
     { 
      return this.length; 
     } 
     set 
     { 
      throw new NotSupportedException(); 
     } 
    } 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     throw new NotSupportedException(); 
    } 

    public override long Seek(long offset, SeekOrigin origin) 
    { 
     throw new NotSupportedException(); 
    } 

    public override void SetLength(long value) 
    { 
     throw new NotSupportedException(); 
    } 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     this.length += count; 
    } 
} 

using (var nul = new NulStream()) 
{ 
    xml.Serialize(nul, lst); 
    long length = nul.Length; 
} 

Это поток NUL ... как файл NUL :-) Это будет есть то, что вы бросаете на нее, и сохранить только кумулятивную длину ,

Обратите внимание, что технически я мог бы реализовать SetLength, а Write должен проверить его параметры ... Но почему? :-)

+0

С помощью этого метода он не будет хранить сериализованный байт в LOH? Потому что это оригинальная проблема – RPDeshaies

+1

@ Tareck117 Нет, это не так. Поскольку 'XmlSerializer' отправляет потоку часть за раз, 1024-2048 байтов из некоторых экспериментов. Если вы хотите его увидеть, добавьте эту строку в переопределение void Write (...): Console.WriteLine (count); – xanatos

Смежные вопросы