Heim >Backend-Entwicklung >Golang >Warum generieren Python und Go zlib unterschiedliche komprimierte Ausgaben für dieselbe Eingabe?

Warum generieren Python und Go zlib unterschiedliche komprimierte Ausgaben für dieselbe Eingabe?

DDD
DDDOriginal
2024-10-29 06:16:02680Durchsuche

 Why do Python and Go zlib generate different compressed output for the same input?

Golang vs. Python zlib: Analyse der Ausgabeunterschiede

In den bereitgestellten Codefragmenten versuchen Sie, eine Zeichenfolge mit beiden Pythons zu komprimieren Das Flate-Paket von zlib und Go. Allerdings liefert Ihre Python-Implementierung eine andere Ausgabe als das Go-Gegenstück. Warum ist das so?

Um das Debuggen zu unterstützen, analysieren wir die relevanten Codefragmente:

Go-Implementierung (compress.go)

<code class="go">package main

import (
    "compress/flate"
    "bytes"
    "fmt"
)

func compress(source string) []byte {
    w, _ := flate.NewWriter(nil, 7)
    buf := new(bytes.Buffer)

    w.Reset(buf)
    w.Write([]byte(source))
    w.Close()

    return buf.Bytes()
}

func main() {
    example := "foo"
    compressed := compress(example)
    fmt.Println(compressed)
}</code>

Der wichtigste Schritt im Go-Code ist das Schließen des Writers, der die komprimierten Daten löscht und eine Prüfsumme ans Ende schreibt.

Python-Implementierung (compress.py)

<code class="python">from __future__ import print_function

import zlib


def compress(source):
    # golang zlib strips header + checksum
    compressor = zlib.compressobj(7, zlib.DEFLATED, -15)
    compressor.compress(source)
    # python zlib defaults to Z_FLUSH, but 
    # https://golang.org/pkg/compress/flate/#Writer.Flush
    # says "Flush is equivalent to Z_SYNC_FLUSH"
    return compressor.flush(zlib.Z_SYNC_FLUSH)


def main():
    example = u"foo"
    compressed = compress(example)
    print(list(bytearray(compressed)))


if __name__ == "__main__":
    main()</code>

Hier haben Sie den Kompressor explizit geleert, indem Sie compress.flush(zlib.Z_SYNC_FLUSH) aufgerufen haben.

Ausgabe zerlegen

Die Python-Ausgabe enthält ein fünftes Byte von 0, während Go 4 hat. Ersteres ist das Ergebnis der Behandlung des Datenendes durch Zlib. Letzteres ist darauf zurückzuführen, dass Flate beim Schließen des Writers den Header und die Prüfsumme entfernt.

Überbrückung der Ausgabelücke

Um eine vergleichbare Ausgabe beider Implementierungen zu erhalten, können Sie entweder:

  1. Verwenden Sie Flush() in Go: Ersetzen Sie w.Close() durch w.Flush() in Ihrem Go-Code, um die komprimierten Daten ohne Prüfsumme auszugeben.

    <code class="go">buf := new(bytes.Buffer)
     w, _ := flate.NewWriter(buf, 7)
     w.Write([]byte(source))
     w.Flush()
    
     return buf.Bytes()</code>
  2. Python-Zlib-Einstellungen anpassen: Ich habe nicht persönlich untersucht, ob Sie Pythons Zlib zwingen können, den vollständigen DEFLATE-Stream ohne Header oder Prüfsummen auszugeben. Dies könnte jedoch ein fruchtbarer Weg sein.

Fazit

Während Sie möglicherweise Parameter anpassen können, um eine Byte-für-Byte-Übereinstimmung zu erzwingen zwischen den beiden Implementierungen ist dies weder notwendig noch wünschenswert. Die Ausgabekompatibilität zwischen verschiedenen Komprimierungsbibliotheken ist garantiert, aber nicht identisch.

Das obige ist der detaillierte Inhalt vonWarum generieren Python und Go zlib unterschiedliche komprimierte Ausgaben für dieselbe Eingabe?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn