Essayez de créer un fichier compressé en utilisant Python et zlib

introduction

Calendrier de l'Avent du Département étudiant LOCAL Jour 6

J'ai grandi en écrivant l'article le 11ème jour, alors je vais remplir l'espace vide.

Qu'est-ce que zlib?

Aperçu

Officiel: zlib.net Il s'agit d'une bibliothèque d'algorithmes de compression utilisés pour Zip, etc., et Deflate est implémenté en interne. Puisque les données binaires peuvent être facilement compressées, elles peuvent être utilisées pour la communication. (Je n'ai jamais essayé) Vous pouvez voir beaucoup de choses en matière de compression de fichiers.

license La licence zlib est appliquée à zlib. C'est une licence assez lâche similaire au MIT. Veuillez vérifier les détails.

Essayez d'utiliser

Pour plus d'informations, veuillez consulter ici compress(data: bytes, level: int = -1) -> bytes Compresse en arrière data. «level» est le taux de compression. Contient des valeurs de «-1 à 9», avec une valeur par défaut de «-1» (équivalente à «6» au 5 décembre 2019). «0» est non compressé et «9» a le taux de compression le plus élevé. Plus le taux de compression est élevé, plus cela prendra du temps, donc dans la plupart des cas, vous pouvez laisser la valeur par défaut.

compress()


import zlib

data = b'test data\x00' #Données binaires arbitraires
compressed = zlib.compress(data)
print(compressed) # b'x\x9c+I-.QHI,Id\x00\x00\x159\x03{'

decompress(data: bytes, wbits: int = 15, bufsize: int = 16384) -> bytes Décompressez et renvoyez «data». Les autres arguments sont fondamentalement bons par défaut. bufsize est incrémenté selon les besoins.

decompress()


import zlib

data = b'test data\x00' #Données binaires arbitraires
decompressed = zlib.decompress(zlib.compress(data))
print(decompressed) # b'test data\x00'

compressobj(level: int = -1, method: int = 8, wbits: int = 15, memLevel: int = 8, strategy: int = 0, zdict: bytes = ...) -> _Compress Renvoie un objet compressé pour compresser des données qui ne peuvent pas être stockées en mémoire en une seule fois. «level» est le même que «compress ()». method est un algorithme de compression et depuis le 5 décembre 2019, la seule valeur prise en charge est DEFLATED = 8 zdict est un dictionnaire compressé prédéfini, une séquence d'octets que vous prévoyez d'apparaître à plusieurs reprises dans vos données.

compressobj()


import zlib
import io

data_stream = io.BytesIO(b'test data\x00')
cobj = zlib.compressobj()
compressed = b''
while True:
    tmp = data_stream.read(64)
    if not tmp:
        compressed += cobj.flush()
        break
    compressed += cobj.compress(tmp)

print(compressed) # b'x\x9c+I-.QHI,Id\x00\x00\x159\x03{'

Oublier le dernier flush () peut entraîner des données incomplètes.

decompressobj(wbits: int = 15, zdict: bytes = ...) -> _Decompress Le zdict doit être le même que celui utilisé dans compressobj (). Aussi, ne changez pas l'objet passé à zdict entre l'appel à decompressobj () et le premier appel à decompress ().

decompressobj()


import zlib
import io

data_stream = io.BytesIO(zlib.compress(b'test data\x00'))
dobj = zlib.decompressobj()
decompressed = b''
while True:
    tmp = data_stream.read(64)
    if not tmp:
        decompressed += dobj.flush()
        break
    while True:
        if not tmp:
            break
        decompressed += dobj.decompress(tmp)
        tmp = dobj.unconsumed_tail

print(decompressed) # b'test data\x00'

Les octets qui ne rentrent pas dans le tampon et qui n'ont pas été traités par l'appel decompress () vont dans ʻunconsumed_tail`.

Créer un fichier compressé

Construction

Il est enregistré dans l'ordre «en-tête, nom de fichier et chemin, fichier_comprimé», et ce bloc est répété pour le nombre de fichiers.

file_header


| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 |
|---------------------------------------|
| name_len(uint_32) | file_len(uint_32) |
|---------------------------------------|

la mise en oeuvre

Il peut être utilisé avec python mcp.py TARGET [-o OUTPUT]. «TARGET» est le chemin du fichier ou du répertoire. Je ne l'ai pas écrit pour une utilisation réelle, donc si vous l'utilisez, veuillez le faire à vos propres risques. La décompression se fera le 11e calendrier de l'Avent.

mcp.py


import sys
import argparse
import os
import zlib
from ctypes import *
import random
import string
import glob
import io
import shutil

tmp_dir = ''.join(random.choices(
    string.ascii_letters + string.digits, k=64))+'_mcptmp'


def main():
    p = argparse.ArgumentParser(
        description='Compress file and dir', usage='Add target to Command line arguments')
    p.add_argument('target', help='Compression target')
    p.add_argument('--out', '-o', help='Output file path',
                   default='compressed.mcp')
    if len(sys.argv) < 2:
        p.print_help()
    target = p.parse_args().target
    out = p.parse_args().out

    if os.path.isfile(target):
        _compress_file(target, out)
    elif os.path.isdir(target):
        _compress_dir(target, out)
    else:
        raise Exception('Argument error')


def _compress_file(path: str, out: str):
    _create_mtp(os.path.basename(path), path)
    size = os.path.getsize(os.path.join(tmp_dir, os.path.basename(path)))
    with open(os.path.join(tmp_dir, os.path.basename(path)), 'rb') as t:
        with open(out, 'wb') as o:
            o.write(_make_file_header(size, os.path.basename(path)))
            while True:
                tmp = t.read(1024)
                if not tmp:
                    o.flush()
                    break
                o.write(tmp)


def _make_file_header(file_len: int, filename: str) -> bytes:
    filename_len = len(filename)
    return bytes(FileHeaderStructure(filename_len, file_len)) + filename.encode('UTF-8')


def _compress_dir(path: str, out: str):
    files = [p[len(path)-1 + len(os.sep):] for p in glob.glob(
        os.path.join(path, '**'), recursive=True) if os.path.isfile(p)]
    for f in files:
        os.makedirs(os.path.join(tmp_dir, os.path.dirname(f)), exist_ok=True)
        _create_mtp(f, os.path.join(path, f))

    with open(out, 'wb') as o:
        for f in files:
            o.write(_make_file_header(
                os.path.getsize(os.path.join(tmp_dir, f)), f))
            with open(os.path.join(tmp_dir, f), 'rb') as t:
                while True:
                    tmp = t.read(1024)
                    if not tmp:
                        break
                    o.write(tmp)
        o.flush()


def _create_mtp(path: str, source: str):
    c = zlib.compressobj()
    with open(source, mode='rb') as f:
        with open(os.path.join(tmp_dir, path), mode='wb') as o:
            while True:
                t = f.read(1024)
                if not t:
                    o.write(c.flush())
                    break
                ced = c.compress(t)
                if ced:
                    o.write(ced)


def _rem_tmp():
    shutil.rmtree(tmp_dir)


class FileHeaderStructure(Structure):
    _fields_ = (
        ('filename_len', c_uint32),
        ('file_len', c_uint32)
    )


if __name__ == "__main__":
    main()
    _rem_tmp()

Je ne peux pas penser à un moyen d'obtenir la taille après la compression, donc je sortie le fichier compressé dans un fichier et obtiens la taille de ce fichier. Si vous mettez la version compressée en mémoire, vous pouvez l'obtenir avec len (), mais alors il ne sert à rien d'utiliser compressobj () ...

J'ai eu du mal à créer les en-têtes attachés aux données du fichier. Je ne suis pas bon en Python, donc je pense que je peux le faire avec C ++. Il n'y a pas de structure en Python, mais il semble que vous puissiez créer quelque chose comme ça en utilisant une classe qui hérite de Structure. Écrivez la structure dans _fields_ par à partir de ctypes import *. Il semble y avoir struct.pack (format, valeurs ...), mais il semble qu'il ne supporte que les ~~ entiers (généralement utilisables) ~~ Il semble que presque tous les types principaux prennent en charge (Documentation.

Recommended Posts

Essayez de créer un fichier compressé en utilisant Python et zlib
Essayez de créer le format de fichier DeepZoom .DZI en Python
Créer un fichier power simple avec Python
Traitez le résultat de l'exécution de Splunk en utilisant Python et enregistrez-le dans un fichier
Créer une lecture de feuille de notes avec Python OpenCV (Conseils pour bien lire)
Créer un fichier GIF en utilisant Pillow en Python
Créer une carte Web en utilisant Python et GDAL
J'ai essayé de lire un fichier CSV en utilisant Python
Exécutez des fichiers Python à partir de HTML en utilisant Django
Essayez d'utiliser tensorflow ① Créez un environnement python et introduisez tensorflow
Créez un fichier MIDI en Python en utilisant pretty_midi
Essayez d'utiliser l'API ChatWork et l'API Qiita en Python
Essayez d'utiliser Tweepy [Python2.7]
Essayez d'obtenir une page Web et un fichier JSON en utilisant la bibliothèque Requests de Python
Création d'un système de contrôle de température avec tarte aux framboises et ESP32 (3) Réception d'un fichier Python
Python: création d'un environnement virtuel (venv), démarrage et arrêt
(Python) Essayez de développer une application Web en utilisant Django
Créez un graphique à l'aide du bouton et du curseur de l'intrigue
Implémentation d'un générateur en utilisant Python> link> yield et next ()> yield
[Python] Démarrez un fichier de commandes à partir de Python et passez des variables.
[Python] Essayez d'utiliser le canevas de Tkinter
Essayez d'utiliser Kubernetes Client -Python-
Lire et écrire des fichiers
Écrire et lire des fichiers
Essayez d'utiliser pytest-Overview and Samples-
Essayez de le faire avec GUI, PyQt en Python
Essayez d'exploiter un fichier Excel en utilisant Python (Pandas / XlsxWriter) ①
Construire un environnement Python sur un Mac, jusqu'au point d'utiliser Jupyter Lab
Essayez d'exploiter un fichier Excel en utilisant Python (Pandas / XlsxWriter) ②
[Python] Chapitre 01-03 À propos de Python (Ecrire et exécuter un programme à l'aide de PyCharm)
Essayez une recherche similaire de recherche d'images à l'aide du SDK Python [Recherche]
Une note lors de la création d'un graphe dirigé à l'aide de Graphviz en Python
Essayez d'ouvrir une sous-fenêtre avec PyQt5 et Python
Essayez de créer un réseau de neurones en Python sans utiliser de bibliothèque
Essayez d'exécuter une fonction écrite en Python à l'aide de Fn Project
Tirez en accéléré à partir d'une caméra PC en utilisant Python, OpenCV
Essayez simplement de recevoir un webhook avec ngrok et Python
J'ai créé Chatbot en utilisant l'API LINE Messaging et Python
Créer une application Web avec Flask ②
Création d'un programme de fractionnement de fichiers wav
J'ai fait un Line-bot avec Python!
Créer une interface graphique python à l'aide de tkinter
Python: Introduction à Flask: création d'une application d'identification de numéro à l'aide de MNIST
Authentification à l'aide de l'authentification des utilisateurs tweepy et de l'authentification d'application (Python)
Créez un classement de jeu sur le cloud Alibaba en utilisant Python et Redis
Dessiner une courbe Silverstone en utilisant Python
Essayez d'utiliser virtualenv qui peut créer un environnement virtuel de Python
Essayez d'utiliser l'API de Pleasant (python / FastAPI)
Essayez d'utiliser LevelDB avec Python (plyvel)
Créer un tableau simple à l'aide de prettytable
Créer un fichier binaire en Python
Un peu plus sur les références ~ Prenant Python et Java comme exemples ~
Créez un lot planifié simple à l'aide de l'image Python de Docker et de parse-crontab
Lecture et écriture de fichiers CSV Python
Créez et essayez un environnement OpenCV et Python en quelques minutes à l'aide de Docker
[Python] Comment récupérer un fichier html local et le générer au format CSV à l'aide de Beautiful Soup
Traitement d'ajout de colonne de fichier Excel et de suppression de ligne à l'aide de Python Openpyxl
Clustering et visualisation à l'aide de Python et CytoScape
J'ai comparé Node.js et Python lors de la création d'une miniature à l'aide d'AWS Lambda