2012-08-23 4 views
2

저는 분명히 뭔가 분명한 것을 놓치고 있습니다. 그러나 두 번째 경우에 더 나은 압축률이 왜 있는지 설명 할 수 있습니까?!하나 또는 두 개의 메모리 스트림을 사용하는 gZipStream을 사용하면 큰 차이가 있습니다.

사례 1 : 압축률이 매우 낮고 때로는 크기도 커집니다.

using (var memoryStream = new System.IO.MemoryStream()) 
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress)) 
{ 
    new BinaryFormatter().Serialize(gZipStream, obj); 
    gZipStream.Close(); 
    return memoryStream.ToArray(); 
} 

사례 2 : 압축률이 훨씬 높고 크기가 커지지 않습니다.

미러 압축 해제를 수행했으며 두 경우 모두 아무 문제없이 원본 개체로 deserialize 할 수 있습니다.

UncSize : 58062085B, COMP1 : 여기

일부 스탯이다 46828139B, 0.81 %

UncSize : 58062085B, COMP2 : 31326029B 0.54 %

UncSize : 7624735B, COMP1 : 7743947B 1.02 %

UncSize : 7624735B, COMP2 : 5337522B, 0.70 %

UncSize 1 237628B, COMP1 : 1265406B, 1.02 %

UncSize : 1237628B, COMP2 : 921695B, 0.74 %

답변

7

당신은 당신이 사용하고 .NET의 버전 말을하지 않습니다. 4.0 이전 버전에서는 GZipStream이 데이터 단위로 데이터를 압축합니다. 즉, 전송 한 버퍼를 압축합니다. 첫 번째 예제에서 Serialize 메서드는 스트림에 매우 작은 버퍼를 쓰는 경향이 있습니다 (한 번에 한 필드 씩). 두 번째 예제에서 Serialize은 전체 개체를 메모리 스트림에 serialize 한 다음 메모리 스트림의 버퍼를 하나의 큰 청크에 GZipStream에 기록합니다. GZipStream은 더 큰 버퍼 (64K가 최적에 가깝습니다)가있을 때 훨씬 잘 작동합니다.

.NET 4.0에서는 여전히 그렇습니다. 나는 그것을 테스트했는지 기억하지 못합니다.

내가 과거에이 문제를 처리 한 방법은 BufferedStream 함께 :

using (var mstream = new MemoryStream()) 
{ 
    using (var bstream = new BufferedStream(new GZipStream(mstream, CompressionMode.Compress), 65536)) 
    { 
     new BinaryFormatter().Serialize(btream, obj); 
    } 
    return mstream.ToArray(); 
} 

그런 식으로, 압축기가 작동 할 수있는 64K 버퍼를 가져옵니다.

.NET 4.0 이전에는 GZipStream에 대해 64K보다 큰 버퍼를 제공하면 아무런 이점이 없었습니다. .NET 4.0의 압축기가 더 큰 버퍼로 더 나은 압축 작업을 할 수 있다는 정보를 보았습니다. 그러나, 나 자신을 테스트하지 않았습니다.

+0

감사합니다. 이것은 내가 찾고 있었던 바로 그 것이다. .net 4.0을 사용 중입니다. 아직 여기에 해당합니다. 당신이 말한대로 64k가 가장 효과적입니다. 버퍼가 작 으면 압축이 약합니다. 더 나은 메모리 관리를 위해 두 개의 메모리 스트림 대신 BufferStream을 사용하도록 코드를 변경했습니다. 감사 – Marek