2009-07-10 5 views
0

Это проблема с C#. У меня есть большой объект в памяти в определенное время. Я хочу сериализовать его в файл. Для этого есть два шага. 1st, мне нужно изменить объект на строку csv. Во-вторых, мне нужно сериализовать строку csv.Как уменьшить потребление памяти?

У меня есть утилита, которая может добавлять строки в MemoryStream. Я использую этот утилитный инструмент для преобразования большого объекта в строку csv (в большой строке MemoryStream). После преобразования большого объекта в MemoryStream я создаю StreamReader из MemoryStream и вызываю его метод StreamReader.ReadToEnd() для преобразования MemoryStream в (длинную) строку. Затем я вызываю info.AddValue («BigObject», строка); для сериализации строки.

Как видно, в памяти я фактически буду хранить три копии большого объекта. Первый - это сам объект, второй - MemoryStream, содержащий строку csv, а третья - это строка, которая на самом деле является избыточной памяти MemoryStream.

Есть ли способ уменьшить потребление памяти в этой процедуре? Похоже, что если не MemoryStream, мне все равно придется использовать StringBuilder для хранения строки csv большого объекта, и мне все равно нужно будет вызвать StringBuilder.ToString(), чтобы получить окончательную строку. Затем финальная строка и StringBuilder будут сосуществовать в памяти и потреблять тот же объем памяти, что и в настоящее время MemoryStream и string.

Любая идея приветствуется. Спасибо.

+0

Я не думаю, что 'StringBuilder.ToString()' фактически возвращает отдельную выделенную строку, чтобы, по крайней мере, сохранить одну копию. – jerryjvl

+0

Насколько велики эти большие объекты кстати? ... если он преодолеет магический (текущий) предел в 85 КБ, у вас могут возникнуть другие проблемы, связанные с фрагментацией памяти. – jerryjvl

+0

jerryvl, вы правы, что он не копирует новую строку. Тем не менее, строка действительно перераспределяется внутри, когда она превышает ее предел, используя алгоритм удвоения. Итак, если у меня есть правильная математика, это приведет к распределению в два раза больше памяти, чем возвращаемая строка, в кусках разных размеров. –

ответ

1

Если вы беспокоитесь о пиковой памяти, я полагаю, вы можете вручную принудительно собрать мусорную корзину после того, как вы закончите с объектом orignal, а затем снова после завершения потока памяти.

(Позвольте мне указать на то, что, в то время как есть несколько случаев, когда взятие под контроль сбора мусора необходимо, это вообще плохая идея. Как правило, это лучше, чтобы вещи получить собранные в свое время.)

+0

Реализация интерфейса IDisposable или деконструктора не поможет с тремя копиями объекта, выделенного в куче одновременно. –

+0

На самом деле, эта статья говорит об этом довольно хорошо. Если вы когда-либо называли GC.Collect(); затем дайте ему прочитать. http://lyontamers.com/blogs/jimlyon/archive/2008/08/29/garbage-collection-finalizers-and-dispose-what-every-c-programmer-should-know.aspx –

+0

Нет, но обнуление всех ссылки и вызов GC вызовут немедленное освобождение памяти. Я проверю статью, спасибо. –

0

Вам не нужно реализовывать собственную сериализацию. Вы можете оставить его в .NET framework. Хорошую отправную точку можно найти here.

1

Попробуйте выполнить следующие задачи.

 public void SerializeToFile<T>(T target, string filename) 
     { 
      XmlSerializer serializer = new XmlSerializer(typeof (T)); 

      using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write)) 
      { 
       serializer.Serialize(stream, target); 
      } 
     } 

Edit: Предположим, что вы можете получить объект для реализации ISerializable и связать вашу программу в метод GetObjectData.

Редактировать2: Пропущен CSV-часть. Icky. Попробуйте использовать XSLT в XML после его сериализации.

Ссылка на article о преобразовании xml в csv через xslt.

0

О каких данных мы говорим? Если это текстовые данные, то вы можете использовать сжатие memery и сохранить много памяти таким образом.

+0

Хотите сделать ставку, это электронная таблица? –

0

Вместо того, чтобы иметь промежуточный этап преобразования объекта в строку CSV, вы можете попробовать записать объект в файл при его сериализации. Просто используйте поток файлов вместо MemoryStream при создании CSV. Еще лучше создать метод SerializeToStream для вашего объекта, который принимает какой-либо поток в качестве параметра.

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