Сжать BitArray с помощью GZip в C#

У меня есть BitArray со 100 млн элементов. Это около 12,5 млн. Я должен сжать этот массив. Я использую GZipStream из Framework.

   public static byte[] Compress(byte[] bytData)
    {
        try
        {
            MemoryStream ms = new MemoryStream();
            Stream s = new GZipStream(ms, CompressionMode.Compress);
            s.Write(bytData, 0, bytData.Length);
            s.Close();
            byte[] compressedData = ms.ToArray();
            return compressedData;
        }
        catch
        {
            return null;
        }
    }

    static void Main(string[] args)
    {
        BitArray t = GetArray();
        byte []byteArray = new byte[100000000/8];
        t.CopyTo(byteArray, 0);
        byte[] compressedData = Compress(byteArray);
        Console.WriteLine(compressedData.Length);
    }
    public static BitArray GetArray()
    {
        Random r = new Random();
        BitArray result = new BitArray(100000000);
        for (int i = 0; i < result.Count; i++)
        {
            if (r.NextDouble() > .5)
            {
                result.Set(i, true);
            }
        }
        return result;
    }
}

Но размер переменной compressData равен 12515308. Это больше исходного массива. Любые идеи?

Может быть, мне нужен другой компрессор?


person Leonid    schedule 03.05.2012    source источник
comment
Сжатие работает путем назначения коротких кодов общим последовательностям в данных и длинных кодов редким последовательностям. Если данные полностью случайны, не так много часто встречающихся последовательностей, поэтому результат может оказаться длиннее оригинала. Решение: не сжимайте случайные данные. Или, если вам нужно, просто используйте PRNG (например, Random) и сохраните только начальное значение, а не сгенерированные значения (процедурная генерация).   -  person dtb    schedule 04.05.2012
comment
Спасибо. Мне нужно использовать случайные данные. Я не могу использовать GZip. Может другой компрессор. Это не совсем случайные числа, но фоп POC я использую random . Это похоже на код шифрования пользователей. Это должно быть случайно.   -  person Leonid    schedule 04.05.2012
comment
Сжатие после шифрования часто является плохой идеей (вы несете накладные расходы на сжатие, и фактическое уменьшение размера будет минимальным, если вообще будет, по причине, упомянутой @dtb). Если возможно, попробуйте сжать данные до их шифрования, тогда вы получите наилучшие результаты.   -  person carlosfigueira    schedule 04.05.2012


Ответы (2)


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

person Seth Flowers    schedule 03.05.2012

Ни один компрессор не может сжать действительно случайные данные. (Как было указано, вы можете сжать псевдослучайные данные, если вы можете вывести начальное число и алгоритм.)

Каково ваше приложение? У вас есть реальные данные для проверки?

person Mark Adler    schedule 03.05.2012
comment
Хе-хе-хе, как сжать 64 КБ псевдослучайного числа в четыре байта: [SEED, STREAM_LENGTH]? :) - person JSideris; 14.06.2012