Как сжать экземпляр объекта .net с помощью gzip - PullRequest
5 голосов
/ 08 июня 2009

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

Я хочу иметь возможность сжатия любого ссылочного типа.

У меня есть рабочая версия для сжатия строк .. идея основана на блоге Скотта Хансельмана http://shrinkster.com/173t

есть идеи по сжатию объекта .net?

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

Ответы [ 4 ]

20 голосов
/ 08 июня 2009

Это не будет работать для любого ссылочного типа. Это будет работать для Сериализуемых типов. Подключите BinaryFormatter к потоку сжатия, который передается в файл:

var formatter = new BinaryFormatter();
using (var outputFile = new FileStream("OutputFile", FileMode.CreateNew))
using (var compressionStream = new GZipStream(
                         outputFile, CompressionMode.Compress)) {
   formatter.Serialize(compressionStream, objToSerialize);
   compressionStream.Flush();
}

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

3 голосов
/ 10 мая 2011

Я только что добавил поддержку GZipStream для своего приложения сегодня, чтобы я мог поделиться некоторым кодом здесь;

Сериализация:

using (Stream s = File.Create(PathName))
{
    RijndaelManaged rm = new RijndaelManaged();
    rm.Key = CryptoKey;
    rm.IV = CryptoIV;
    using (CryptoStream cs = new CryptoStream(s, rm.CreateEncryptor(), CryptoStreamMode.Write))
    {
        using (GZipStream gs = new GZipStream(cs, CompressionMode.Compress))
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(gs, _instance);
        }
    }
}

Десериализация:

using (Stream s = File.OpenRead(PathName))
{
    RijndaelManaged rm = new RijndaelManaged();
    rm.Key = CryptoKey;
    rm.IV = CryptoIV;
    using (CryptoStream cs = new CryptoStream(s, rm.CreateDecryptor(), CryptoStreamMode.Read))
    {
        using (GZipStream gs = new GZipStream(cs, CompressionMode.Decompress))
        {
            BinaryFormatter bf = new BinaryFormatter();
            _instance = (Storage)bf.Deserialize(gs);
        }
    }
}

ПРИМЕЧАНИЕ: если вы используете CryptoStream, очень важно правильно (не) зашифровать и (де) зашифровать таким образом, потому что вы захотите потерять энтропию ДО того, как шифрование создаст шум из ваших данных.

3 голосов
/ 08 июня 2009

Какие объекты вы помещаете в кеш? Это напечатанные объекты? Или такие вещи, как DataTable? Для DataTable, возможно, сохраните как xml, сжатый через GZipStream. Для типизированных (сущностных) объектов вам, вероятно, потребуется сериализовать их.

Вы можете использовать BinaryFormatter и GZipStream, или вы можете просто использовать что-то вроде protobuf-net сериализация (бесплатно), которая уже очень компактна (добавление GZipStream обычно делает данные больше - что типично для плотного бинарного файла). В частности, преимущество таких вещей, как protobuf-net, состоит в том, что вы получаете уменьшенный размер без необходимости платить за процессор разархивирование во время десериализации. В некоторых тестах до с добавлением GZipStream это было в 4 раза быстрее, чем BinaryFormatter. Добавьте дополнительное время на BinaryFormatter для GZip, и оно должно выиграть с значительным запасом.

0 голосов
/ 09 июля 2018

Вот как это можно сделать.

GzipStream : предоставляет методы и свойства, используемые для сжатия и распаковки потоков.

Сериализация объекта в поток памяти с использованием бинарного форматирования и привязка этого потока памяти к Gzipstream.

Код для сжатия выглядит следующим образом:

            public static byte[] ObjectToCompressedByteArray(object obj)
                    {
                        try
                        {
                            using (var memoryStream = new System.IO.MemoryStream())
                            {
                                using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
                                {
                                    var binaryFormatter = new BinaryFormatter();
                                    binaryFormatter.Serialize(gZipStream, obj);
                                }
                                return memoryStream.ToArray();
                            }
                        }
                        catch (Exception ex)
                        {
                            LoggerWrapper.CMLogger.LogMessage(
                                $"EXCEPTION: BSExportImportHelper.ObjectToByteArray - : {ex.Message}", LoggerWrapper.CMLogger.CMLogLevel.Error);
                            throw;
                        }

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