2010-09-13 13 views
20

Mam program w języku Python, który pobiera pliki tekstowe jako dane wejściowe. Jednak niektóre z tych plików mogą być skompresowane gzip.Jak sprawdzić, czy plik jest skompresowany gzip?

Czy istnieje platforma wieloplatformowa, którą można wykorzystać w języku Python, aby określić, czy plik jest skompresowany przy użyciu gzip, czy nie?

Czy następujący wiarygodny lub zwykły plik tekstowy "przypadkowo" wygląda na wystarczająco gzip, aby uzyskać fałszywe alarmy?

try: 
    gzip.GzipFile(filename, 'r') 
    # compressed 
    # ... 
except: 
    # not compressed 
    # ... 
+1

Wystarczy mała podpowiedź ... nigdy nie polegaj na zakończeniu pliku. Zobacz odpowiedź na pytanie, jak to zrobić. – helpermethod

+0

@Helper: Nie jestem pewien (zobacz moją edycję). nadal będziesz musiał radzić sobie z możliwym IOError, ale spakowane pliki bez sufiksu są zepsute, moim zdaniem ... trudne połączenie :) – hop

Odpowiedz

34

magic number gzip dla skompresowanych plików jest 1f 8b. Chociaż testowanie tego nie jest w 100% niezawodne, jest bardzo mało prawdopodobne, że "zwykłe pliki tekstowe" zaczynają się od tych dwóch bajtów - w UTF-8 nie jest to nawet legalne.

Zwykle pliki skompresowane gzip mają jednak przyrostek .gz. Nawet sam gzip(1) nie rozpakuje plików bez niego, chyba że do niego zostanie dodany --force. Możesz to wykorzystać, ale nadal musisz poradzić sobie z możliwym IOError (który musisz w każdym razie).

Jednym z problemów z twoim podejściem jest to, że gzip.GzipFile() nie wyrzuci wyjątku, jeśli podasz mu nieskompresowany plik. Tylko później będzie to read(). Oznacza to, że prawdopodobnie będziesz musiał wdrożyć część logiki programu dwa razy. Brzydki.

+0

skompresowane pliki gzip często mają rozszerzenie pliku .gz (w rzeczywistości, nie sądzę, żebym "kiedykolwiek widziałem rozszerzenie .gzip), ale generalnie nie można polegać na rozszerzeniu pliku, aby przetestować typ pliku. – CanSpice

+0

@CanSpice: oczywiście, literówka – hop

+0

Czy to? - Biblioteka gzip C będzie przezroczysto odczytywać nieskompresowane pliki.Chociaż będzie zapisywać pliki bez kompresji, umieszcza je za pomocą kodów CRC, aby zezwolić na "gzip -t" (raz mnie zaskoczyło) –

0

Zaimportuj moduł . Może automatycznie odgadnąć, jaki plik posiadasz i czy jest skompresowany.

tj

mimetypes.guess_type('blabla.txt.gz') 

powraca:

('text/plain', 'gzip')

+12

'mimetypes' sprawdza tylko koniec nazwy pliku, nie jest to zgodne z zawartością pliku. – Odinulf

0

nie wydaje się działać dobrze w python3 ...

import mimetypes 
filename = "./datasets/test" 

def file_type(filename): 
    type = mimetypes.guess_type(filename) 
    return type 
print(file_type(filename)) 

zwraca (brak, brak) Ale z polecenia unix "Plik"

: ~> zestawy danych plików/zestawów danych testowych /test: gzip skompresowane dane, była "iostat_collection", z Unix, ostatnia modyfikacja: Nie Mar 29 07:09:34 2015

+3

mimetypes używa nazwy pliku do odgadnięcia typu. Aby wykryć typ pliku z surowego pliku, musisz użyć modułu "magia". –

2

„Czy jest cross-platform , użyteczne w Pythonie do ustalenia, czy plik jest skompresowany gzip czy nie? "

Przyjęta odpowiedź dostarczyła mi 90% drogi do całkiem niezawodny rozwiązanie (test, jeśli pierwsze dwa bajty są 1f 8b), ale nie pokazał, jak faktycznie to zrobić w Pythonie. Oto jeden z możliwych sposobów:

import binascii 

def is_gz_file(filepath): 
    with open(filepath, 'rb') as test_f: 
     return binascii.hexlify(test_f.read(2)) == b'1f8b' 
Powiązane problemy