Najszybszy sposób opracowania nieskompresowanego rozmiaru dużego pliku GZIPPED


24

Po skompresowaniu pliku istnieje sposób szybkiego zapytania go o rozmiar nieskompresowanego pliku (bez jego dekompresji), szczególnie w przypadkach, gdy rozmiar nieskompresowanego pliku jest większy niż 4 GB.

Zgodnie z RFC https://tools.ietf.org/html/rfc1952#page-5 możesz zapytać o ostatnie 4 bajty pliku, ale jeśli nieskompresowany plik miał> 4 GB, wówczas wartość reprezentuje tylkouncompressed value modulo 2^32

Tę wartość można również odzyskać, uruchamiając gunzip -l foo.gz, jednak kolumna „nieskompresowana” po prostu zawiera uncompressed value modulo 2^32ponownie, prawdopodobnie podczas odczytu stopki, jak opisano powyżej.

Zastanawiałem się tylko, czy istnieje sposób na uzyskanie rozmiaru nieskompresowanego pliku bez konieczności jego pierwszej dekompresji, byłoby to szczególnie przydatne w przypadku, gdy pliki spakowane gzip zawierają ponad 50 GB danych i rozpakowanie ich przy użyciu metod takich jak gzcat foo.gz | wc -c


EDYCJA: Ograniczenie 4 GB jest otwarcie potwierdzone na manstronie gzipnarzędzia dołączonego do OSX ( Apple gzip 242)

  BUGS
    According to RFC 1952, the recorded file size is stored in a 32-bit
    integer, therefore, it can not represent files larger than 4GB. This
    limitation also applies to -l option of gzip utility.

2
+1 dobre pytanie! Podejrzewam, że odpowiedź brzmi „nie”, że format nagłówka został zaprojektowany w czasie poprzedzającym takie rozmiary plików. Myślenie o tym gzipmusi być starsze niż wielu użytkowników w tej społeczności!
— Celada,

2
gzipwyszedł w 1992 roku. Byłbym zaskoczony, gdyby w okolicy kręciło się wielu 23-latków. Jestem pewien, że są takie, ale z tego, co mogę powiedzieć, mediana wieku to około 30-35 lat.
— Bratchley,

2
Może to być dobry moment na przejście na takie, xzktóre nie mają tego ograniczenia. GNU przechodzi na xz.
— Stéphane Chazelas,

@ StéphaneChazelas Ciekawe. Niestety pliki, którymi się interesuję, są poza moją kontrolą (tzn. Otrzymujemy je skompresowane), ale z pewnością wygląda na to, xz że „rozwiązałoby” ten problem.
— djhworld,

Odpowiedzi:


11

Uważam, że najszybszym sposobem jest modyfikacja gzip, aby testowanie w trybie pełnym wyświetlał liczbę zdekompresowanych bajtów; w moim systemie, z plikiem 7761108684-bajt, dostaję

% time gzip -tv test.gz
test.gz:     OK (7761108684 bytes)
gzip -tv test.gz  44.19s user 0.79s system 100% cpu 44.919 total

% time zcat test.gz| wc -c
7761108684
zcat test.gz  45.51s user 1.54s system 100% cpu 46.987 total
wc -c  0.09s user 1.46s system 3% cpu 46.987 total

Aby zmodyfikować gzip (1.6, dostępny w Debianie), łatka wygląda następująco:

--- a/gzip.c
+++ b/gzip.c
@@ -61,6 +61,7 @@
 #include <stdbool.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <inttypes.h>

 #include "closein.h"
 #include "tailor.h"
@@ -694,7 +695,7 @@

     if (verbose) {
         if (test) {
-            fprintf(stderr, " OK\n");
+            fprintf(stderr, " OK (%jd bytes)\n", (intmax_t) bytes_out);

         } else if (!decompress) {
             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
@@ -901,7 +902,7 @@
     /* Display statistics */
     if(verbose) {
         if (test) {
-            fprintf(stderr, " OK");
+            fprintf(stderr, " OK (%jd bytes)", (intmax_t) bytes_out);
         } else if (decompress) {
             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
         } else {

Czy nadal buduje rzeczywiste dane wewnętrznie, czy jest -tjuż zoptymalizowany pod tym względem? Ulepszenie jest wystarczająco małe, aby wyglądało na to, że zaoszczędziłeś tylko czas wyjściowy.
— frostschutz

Tak, musi zdekompresować wszystko, aby ustalić oryginalny rozmiar ... To oszczędza tylko czas wyjściowy, ale myślę, że to wszystko, co można zapisać.
— Stephen Kitt

Ciekawe, tak, myślałem, że trzeba zmienić kod, aby faktycznie to zadziałało. Niestety w moim przypadku pliki, które mnie interesują, tak naprawdę nie są pod moją kontrolą, otrzymuję je od zewnętrznego podmiotu, więc nie będę w stanie ich skompresować. Myślę, że jedynym sposobem na pełną obsługę plików> 4 GB byłoby załatanie gzip, aby miał 12-bajtową stopkę, 4 bajty dla CRC i 8 bajtów (64-bit) dla rozmiaru pliku. Jednak to zepsuje kompatybilność wsteczną z istniejącymi gzips!
— djhworld

Rozwiązanie, które podałem powyżej, nie obejmuje początkowej kompresji plików, nawet jeśli działam gzip; Po prostu uruchamiam gzipskompresowane pliki, które nie kompresują ich, tylko je weryfikują. (Łata jest szybkim i brudnym sprawdzianem koncepcji, wymaga kilku dodatkowych zmian do pracy gunzip.)
— Stephen Kitt

@StephenKitt Ah ciekawe! Jeszcze lepszym / bardziej brudnym włamaniem byłoby osadzenie tych danych w FCOMMENTterenie. W ten sposób użytkownicy mogą zapytać o zakres bajtów, aby pobrać te dane. Byłoby to przydatne w moim przypadku, szczególnie w przypadku przedmiotów przechowywanych w Amazon S3
— djhworld

0

Jeśli potrzebujesz wielkość skompresowanego pliku lub zestawu plików, najlepiej jest do stosowania tar -zlub tar -jzamiast gzipjako tarobejmuje nieskompresowany format plików. Użyj, lesspipeaby zerknąć na listę plików:

aptitude install lesspipe
lesspipe <compressed file> | less

Jeśli lessjest skonfigurowany do użycia lesspipe:

less <compressed file>

Pamiętaj jednak, że może to potrwać bardzo długo. Jednak twój system pozostaje responsywny, co pozwala zabić proces dekompresji.

Innym podejściem byłoby zalogowanie skompresowanego współczynnika i zapytanie tego pliku [tekstowego] zamiast:

gzip --verbose file 2>&1 | tee file.gz.log
file:    64.5% -- replaced with file.gz

Wymaga jednak obliczeń, aby znaleźć rzeczywisty rozmiar pliku.

Możesz również zrobić to samo z tar, co w rzeczywistości robię z kopiami zapasowymi o dużych rozmiarach, ponieważ zapobiega to przejściu przez cały proces dekompresji, aby uzyskać na przykład tylko rozmiar lub nazwę pliku.


2
Czy tar.gz nie musi być również całkowicie zdekompresowany, aby uzyskać listę wszystkich plików?
— frostschutz

Rzeczywiście tak musi być. To jedyny sposób na uzyskanie nieskompresowanego rozmiaru pliku. Z tarmasz oryginalny rozmiar pliku zalogowany w archiwum. Z zipdrugiej strony nie jestem pewien, czy zachowuje się inaczej.

1
W tym momencie OP może równie dobrze wykonać wc -cpolecenie.
— Bratchley,

@Bratchley oczywiście. Ale uzyskanie wszystkich wyników zajęłoby sporo czasu. Stąd moje dwie sugestie dotyczące rejestrowania rozmiarów plików.

0

Co powiesz na

gzip -l file.gz|tail -n1|awk '{print $2}'

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')

1
To nie działa w przypadku dużych plików, jak wyjaśniono w OP.
— Stephen Kitt

-2
gunzip -c $file | wc -c

To zajmie dużo czasu, ale da ci ostateczny rozmiar w bajtach.


5
Właśnie tego PO stara się unikać.
— depquid
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.