Maison > développement back-end > Golang > Pourquoi Python et Go zlib génèrent-ils une sortie compressée différente pour la même entrée ?

Pourquoi Python et Go zlib génèrent-ils une sortie compressée différente pour la même entrée ?

DDD
Libérer: 2024-10-29 06:16:02
original
682 Les gens l'ont consulté

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

Golang vs Python zlib : disséquer les différences de sortie

Dans les extraits de code fournis, vous essayez de compresser une chaîne en utilisant les deux langages de Python Le package flate de zlib et Go. Cependant, votre implémentation Python produit un résultat différent de celui de son homologue Go. Pourquoi est-ce le cas ?

Pour faciliter le débogage, analysons les fragments de code pertinents :

Implémentation Go (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>
Copier après la connexion

L'étape clé du code Go consiste à fermer le Writer, qui vide les données compressées et écrit une somme de contrôle à la fin.

Implémentation Python (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>
Copier après la connexion

Ici, vous avez explicitement vidé le compresseur en appelant compresseur.flush(zlib.Z_SYNC_FLUSH).

Disséquer la sortie

La sortie Python contient un cinquième octet de 0, alors que Go en a 4. Le premier est le résultat de la gestion par Zlib de la fin des données. Ce dernier est dû au fait que Flate a supprimé l'en-tête et la somme de contrôle lors de la fermeture du rédacteur.

Combler l'écart de sortie

Pour obtenir un résultat comparable des deux implémentations, vous pouvez soit :

  1. Utilisez Flush() dans Go : Remplacez w.Close() par w.Flush() dans votre code Go pour émettre les données compressées sans la somme de contrôle.

    <code class="go">buf := new(bytes.Buffer)
     w, _ := flate.NewWriter(buf, 7)
     w.Write([]byte(source))
     w.Flush()
    
     return buf.Bytes()</code>
    Copier après la connexion
  2. Modifier les paramètres Zlib de Python : Je n'ai pas personnellement exploré si vous pouvez forcer le zlib de Python à générer le flux DEFLATE complet sans en-têtes ni sommes de contrôle. Cependant, cela pourrait être une voie fructueuse à suivre.

Conclusion

Bien que vous puissiez peut-être modifier les paramètres pour forcer une correspondance octet par octet entre les deux implémentations, cela n’est ni nécessaire ni même souhaitable. La compatibilité de sortie entre les différentes bibliothèques de compression est garantie mais pas identique.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal