문제

System.IO.Compression.GZipStream 또는 System.IO.Compression.Deflate는 zlib 압축과 호환됩니까?

도움이 되었습니까?

해결책

에서 MSDN System.IO.Compression.GZipStream 정보:

이 클래스는 무손실 파일 압축 및 압축 해제를 위한 업계 표준 알고리즘을 사용하는 gzip 데이터 형식을 나타냅니다.

로부터 zlib FAQ:

반면에 zlib의 gz* 함수는 gzip 형식을 사용합니다.

따라서 zlib와 GZipStream은 상호 운용 가능해야 하지만 gzip 형식을 처리하기 위해 zlib 함수를 사용하는 경우에만 가능합니다.

System.IO.Compression.Deflate와 zlib는 상호 운용이 불가능한 것으로 알려졌습니다.

zip 파일을 처리해야 하는 경우(아마도 그렇지 않을 수도 있지만 다른 사람이 필요할 수도 있음) 다음을 사용해야 합니다. SharpZipLib 또는 다른 타사 라이브러리.

다른 팁

DotNetZip RFC 1950, 1951 및 1952를 처리하기 위한 DeflateStream, ZlibStream 및 GZipStream이 포함되어 있습니다.모두 DEFLATE 알고리즘을 사용하지만 프레임과 헤더 바이트는 각각 다릅니다.

장점으로 DotNetZip의 스트림은 데이터 크기 확장의 이상 압축 시 내장 스트림에 대해 보고됩니다.또한 ZlibStream이 내장되어 있지 않지만 DotNetZip은 zlib와의 우수한 상호 운용성을 제공합니다.

Git 개체에서 이 문제가 발생했습니다.특별한 경우에는 개체를 Zlib 헤더가 있는 수축된 blob으로 저장합니다. 이는 다음 문서에 설명되어 있습니다. RFC 1950.다음을 포함하는 파일을 만들어 호환 가능한 blob을 만들 수 있습니다.

  • 값이 포함된 2개의 헤더 바이트(RFC 1950의 CMF 및 FLG) 0x78 0x01
    • CM = 8 = 수축
    • CINFO = 7 = 32Kb 창
    • FCHECK = 1 = 이 헤더의 체크섬 비트
  • C#의 출력 DeflateStream
  • 입력 데이터의 Adler32 체크섬 DeflateStream, 빅엔디안 형식(MSB 우선)

나만의 Adler 구현을 만들었습니다.

public class Adler32Computer
{
    private int a = 1;
    private int b = 0;

    public int Checksum
    {
        get
        {
            return ((b * 65536) + a);
        }
    }

    private static readonly int Modulus = 65521;

    public void Update(byte[] data, int offset, int length)
    {
        for (int counter = 0; counter < length; ++counter)
        {
            a = (a + (data[offset + counter])) % Modulus;
            b = (b + a) % Modulus;
        }
    }
}

그리고 그게 거의 전부였습니다.

나는 GZipStream을 사용하여 .NET XmlSerializer의 출력을 압축했으며 gunzip(cygwin의 경우), winzip 및 다른 GZipStream을 사용하여 결과의 ​​압축을 풀 때 완벽하게 작동했습니다.

참고로 제가 코드에서 수행한 작업은 다음과 같습니다.

FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
using (GZipStream gzStream = new GZipStream(fs, CompressionMode.Compress))
{
  XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
  serializer.Serialize(gzStream, myData);
}

그런 다음 C#에서 압축을 풀려면

FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
using (Stream input = new GZipStream(fs, CompressionMode.Decompress))
{
   XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
   myData = (MyDataType) serializer.Deserialize(input);
}

cygwin에서 'file' 유틸리티를 사용하면 GZipStream으로 압축된 동일한 파일과 GNU GZip으로 압축된 동일한 파일 사이에 실제로 차이가 있음이 드러납니다(아마도 이 스레드에서 다른 사람들이 언급한 헤더 정보일 것입니다).그러나 이 차이는 실제로는 중요하지 않은 것 같습니다.

gzip은 수축 + 체크섬 및 길이 등과 같은 일부 머리글/바닥글 데이터입니다.따라서 한 방법이 다른 방법의 스트림을 사용할 수 있다는 점에서 호환되지 않지만 동일한 압축 알고리즘을 사용합니다.

zlib 또는 deflate 알고리즘을 사용하여 데이터를 압축하지만 일부 특정 파일 형식에 대한 출력은 제공하지 않습니다.즉, 스트림을 있는 그대로 하드 드라이브에 저장하면 파일 헤더(매직 넘버 등)가 스트림에 포함되어 있지 않기 때문에 일부 응용 프로그램(gzip 또는 winrar)을 사용하여 열 수 없을 가능성이 높습니다. 직접 작성해 보세요.

.NET Framework 4.5부터 System.IO.Compression.DeflateStream 클래스는 zlib 라이브러리를 사용합니다.

수업시간부터 MSDN 기사:

이 클래스는 무손실 파일 압축 및 압축 풀기를 위한 업계 표준 알고리즘인 Deflate 알고리즘을 나타냅니다..NET Framework 4.5부터 DeflateStream 클래스는 zlib 라이브러리를 사용합니다.결과적으로 더 나은 압축 알고리즘을 제공하며 대부분의 경우 이전 버전의 .NET Framework에서 제공하는 것보다 더 작은 압축 파일을 제공합니다.

나는 안드레아스의 말에 동의한다.외부 도구에서는 파일을 열 수 없을 수도 있지만 해당 도구에서 스트림을 기대하는 경우에는 사용할 수 있습니다.동일한 압축 클래스를 사용하여 파일을 다시 압축할 수도 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top