2012-03-21 10 views
15

Я столкнулся с каким-то странным поведением GZipStream, зависящим от машины и ОС в .NET 4.0. Это соответствующий код:Зависимость машинной зависимости GZipStream

public static string Compress(string input) { 
    using(var ms = new MemoryStream(Encoding.UTF8.GetBytes(input))) 
    using(var os = new MemoryStream()) { 
     using(var gz = new GZipStream(os,CompressionMode.Compress,true)) { 
      ms.CopyTo(gz); 
     } 
     return string.Join("",os.ToArray().Select(b=>b.ToString("X2"))); 
    } 
} 

Запуск Сжать ("Фрик") дает мне

1F8B08000000000004004B2B4A4DCD06001E33909D05000000 

на Windows 7 и

1F8B0800000000000400ECBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F22CEEB3C7FFBFF040000FFFF1E33909D05000000 

на Windows Server 2008R2. Оба являются 64-битными. Я ожидаю, что результаты будут одинаковыми.

Обе машины дают правильный результат при распаковке любого результата. Я уже выяснил, что на W7 ms.Length == 25 пока на W2K8R2 ms.Length == 128, но не знаю, почему.

Что происходит?

+1

Это может быть так же легко, как и в MemoryStream. Пробовал это без gzip? –

+0

@ Хенк почему ты так думаешь? Является ли MemoryStream другими 123 байтами на W2K8R2? – Freek

+0

Вы проверили в диспетчере задач, если обе машины показывают это как 64-битный процесс или нет? Как ваши настройки сборки? – weismat

ответ

18

It was announced that .NET 4.5 Beta includes zip compression improvements to reduce the size:

Начиная с .NET Framework 4.5 RC, класс DeflateStream использует библиотеку ZLIB для сжатия. В результате он обеспечивает лучший алгоритм сжатия и, в большинстве случаев, меньший сжатый файл, чем он обеспечивает в более ранних версиях .NET Framework.

Возможно, у вас установлена ​​.Net 4.5+ на машине Win7?

+4

Это немного насчет переполнения стека из-за запуска смешанного содержимого 4.0/4.5 и gzipping, прежде чем вставлять его (какие должны быть) уникальные наборы redis для кеширования. Если вы * полагаетесь * на тот же результат сжатия (например, на удаление элемента из набора), остерегайтесь запуска смешанной среды с 4.0 и 4.5 серверами. –

+0

Отлично! Теперь я знаю, как объяснить во время интервью с клиентом, почему моя программа не работает! – VMAtm

0

Я подозреваю, что одна из операционных систем - 32 бит, а другая - 64 бит.

+0

ОП упоминает, что оба являются 64-битными (в обновлении.) –

1

Я побежал код на моем Windows 7 64-битной машине и получил следующий, который приравнивает ваш Win2k8SP2:

1F8B0800000000000400ECBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F229ED579FEF6FF090000FFFF1A1C515C05000000 

По существу, я думаю, что результат должен делать со словом длины машины. Я., ваша машина для Windows-7, возможно, 32 бит?

ПРИМЕЧАНИЕ: Я написал немного распаковки для ваших строк, и я должен сказать, что они действительно хорошо распаковываются. Я запускал свою версию как в 32-битном, так и в 64-битном, и результат был равен. Остается только возможная разница: разные времена работы?

EDIT:

различных сред выполнения?

По-видимому, в качестве Henk Holterman предлагаемых ниже и Robert Levy формализованы в his answer, это было действительно неочевидный случай.

+0

Оба являются 64-битными, забыл упомянуть об этом. – Freek

+0

В какой Visual Studio вы работаете? – Freek

+0

@Freek: VS 2010 Ultimate. – Abel

1

В отличие от Abel «s answer, я получаю результат

1F8B08000000000004004B2B4A4DCD06001E33909D05000000 

на моем Windows 7 x64 Максимальная SP1. Возможно, есть обновление .NET Framework, которое у вас нет в одном из полей? Версия моего mscorlib.dll - 4.0.30319.17379.

ETA: Если я нацелить на .NET 2 (и изменить .NET 4-специфические конструкции для их .NET 2 эквивалента), я получаю результат

1F8B0800000000000400EDBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F22CEEB3C7FFBFF001E33909D05000000 

на ту же машину /ОПЕРАЦИОННЫЕ СИСТЕМЫ.

+0

Я подозреваю, что это из-за обновления SP1. Я тестирую это сейчас. – Freek

+1

У вас установлен 4.5? – Freek

+0

На самом деле, я делаю, на этой коробке. Я прочитал комментарий, который вы сделали повторно: повышенная удушаемость в 4.5, и это ударит ноготь по голове. Хорошая находка! –

5

Кажется, есть изменения в algorithm used by DeflateStream in .NET 4.5:

Начиная с .NET Framework 4.5 Beta, класс DeflateStream использует библиотеку ZLIB для сжатия. В результате он обеспечивает лучший алгоритм сжатия и, в большинстве случаев, меньший сжатый файл, чем он обеспечивает в более ранних версиях .NET Framework.

С тех пор как я установил 4.5, это вызывало проблему.

+2

Я бы не стал считать это изменением. Это просто улучшение производительности. Приложения не должны ожидать каких-либо ожиданий от результата этого API, кроме того, что это действительно для спецификации gzip. –

+0

Это потрясающее изменение, но это хуже, чем нарушение изменений в предыдущих выпусках. .NET 4.5 заменяет .NET 4.0, что означает, что установка приложения на том же компьютере, который использует .NET 4.5, может разорвать уже установленное приложение на том же компьютере, который использует .NET 4.0, но начнет использовать .NET 4.5. – zumalifeguard