2009-07-17 10 views
11

Chcę połączyć dwa lub więcej strumieni gzip bez ich kompresowania.Jak połączyć dwa lub więcej plików/strumieni gzip

Mam na myśli, że mam skompresowane do A.gz i B do B.gz, chcę skompresować je do pojedynczego gzip (A + B) .gz bez kompresji po raz kolejny, używając C lub C++.

Kilka uwag:

  • Nawet można po prostu concat dwa pliki i gunzip będzie wiedział, jak radzić sobie z nimi, większość programów nie będzie w stanie poradzić sobie z dwoma kawałkami.
  • Widziałem kiedyś przykład kodu, który robi to po prostu przez dekompresję plików, a następnie manipulowanie oryginałem i to znacznie szybciej niż normalna ponowna kompresja, ale nadal wymaga operacji O (n) CPU.
  • Niefortunnie Nie mogę znaleźć tego przykładu, który znalazłem raz (konkatenacja tylko przy użyciu dekompresji), jeśli ktoś może wskazać to, byłbym wdzięczny.

Uwaga: nie jest to duplikat this, ponieważ proponowane rozwiązanie nie odpowiada moim potrzebom.

Clearification edit:

Chcę concate kilka skompresowanych pices HTML i wysłać je do przeglądarki jako jednej stronie, jak na żądanie: "Accept-Encoding: gzip", z respnse „Content-Encoding: gzip "

Jeśli strumień jest tak prosty jak cat a.gz b.gz >ab.gz, silniki sieciowe Gecko (firefox) i KHTML pobierają tylko pierwszą część (a); IE6 nie wyświetla niczego, a Google Chrome wyświetla pierwszą część (a) poprawnie, a druga część (b) jako śmieci (w ogóle nie rozpakowuje).

Tylko Opera obsługuje tę funkcję.

Potrzebuję więc utworzyć pojedynczy strumień gzip o wartości i wysłać go bez ponownego kompresowania.

Aktualizacja: Znalazłem gzjoin.c w przykładach zlib, robi to za pomocą dekompresji. Problem polega na tym, że dekompresja jest jeszcze wolniejsza niż prosta.

Jest jeszcze szybsza 4 razy, a następnie najszybsza kompresja gzip. Ale to nie wystarczy.

Potrzebuję znaleźć dane, które muszę zapisać razem z plikiem gzip, aby nie uruchomić procedury dekompresyjnej i jak znaleźć te dane podczas kompresji.

+0

Naprawdę chcesz je skompresować lub po prostu połączyć w jeden plik? –

+0

Chcę utworzyć jeden skompresowany plik gzip/strumień/fragment pamięci dwóch innych skompresowanych plików gzip/strumieni/fragmentów pamięci bez ich dekompresji, utrwalając je i kompresując je ponownie. – Artyom

+0

Zobacz wyjaśnienia w edycji. – Artyom

Odpowiedz

11

Spójrz RFC1951 i RFC1952 Format to po prostu zestaw składający się z członków, z których każdy składa się z trzech części, nagłówka, danych i zwiastuna.Część danych jest sama zbiorem porcji, przy czym każda część ma część nagłówkową i część danych.

Aby symulować efekt gzipingu wyniku konkatenacji dwóch (lub większej liczby plików), należy po prostu dostosować nagłówki (na przykład flaga ostatniej porcji) i zwiastun oraz skopiować części danych.

Istnieje problem, zwiastun ma CRC32 nieskompresowanych danych i nie jestem pewien, czy ten jest łatwy do obliczenia, gdy znasz CRC części.

Edytuj: komentarze w pliku gzjoin.c, które znalazłeś sugerują, że chociaż możliwe jest obliczenie CRC32 bez dekompresji danych, są inne rzeczy, które wymagają dekompresji.

+1

Jeśli posiadasz CRC na kawałki, możesz użyć ich do obliczenia końcowego CRC. Jeśli się nie mylę, jeśli masz Msg1 z Crc1 i Msg2 z Crc2, to aby obliczyć crc z [Msg1, Msg2] możesz zamiast tego obliczyć crc [Crc1, 0,0,0,0 ... (zera Msg2 czas trwania)] i xor to z Crc2. Być może gdzieś będzie potrzebne uzupełnienie, ale idea jest taka. – eugensk00

2

Jeśli tar je ing nie jest wykluczone (ponieważ nie jest związany cat solution opłacalne dla Ciebie):

tar cf A_B.gz.tar A.gz B.gz 

Następnie, aby je odzyskać:

tar xf A_B.gz.tar 
+0

Nie, w ogóle nie mówię o smarze – Artyom

+1

Widzę, co mówisz teraz. . . Chcesz zrobić odpowiednik "gunzip A.gz i guzip B.gz & cat A B> C & gzip C.gz A B", ale bez dekompresji, w nadziei na osiągnięcie czasu przetwarzania O (1). gzip nie zrobi tego i nie wiem, czy istnieje narzędzie, które może. Ale nawet gdyby tak było, wciąż potrzebowałby czasu O (n), ponieważ musiałby (przynajmniej) zbadać skompresowane pliki, aby dowiedzieć się, jak je skompresować. –

+0

Co jest złego w tarowaniu ich, to osiąga wszystko, co chcesz zrobić. –

2

Wygląda na to, że oryginalna kompresja poszczególnych plików jest wykonywana przez Ciebie. Wydaje się również, że pożądany wynik (połączenie kilku elementów) jest wystarczająco mały, aby można go było wysłać do przeglądarki internetowej na jednej stronie. W takim przypadku wątpliwości dotyczące wydajności wydają się być nieuzasadnione.

Należy pamiętać, że (1) podejście gzjoin.c jest wysoce prawdopodobne, aby być najlepszą odpowiedź, że można dostać się do pytania jak podano (2) jest skomplikowany mikrochirurgii wykonywane przez jednego z twórców gzip i nie może zostały poddane rozległym testom warunków skrajnych.

Proszę rozważyć nudne, zrozumiałe i niezawodne podejście: przechowywanie oryginalnych kawałków nieskompresowanych, a następnie wybieranie wymaganych elementów oraz łączenie ich i kompresowanie. Zwróć uwagę, że stopień sprężania może być lepszy niż uzyskany przez sklejanie małych skompresowanych kawałków.

+0

Tak, jestem pomysłodawcą tych dwóch kawałków, więc mogę nawet zapisać niektóre metadane z nimi lub założyć pewne założenia. Rozumiem, że gzjoin jest najprostszy i mniej podatny na błędy, ale wciąż jest tylko 4 razy szybszy niż prosty "gzip -1". Potrzebuję memcpy w pobliżu przyspieszenia. Pomysł: buforuję niektóre gotowe porcje i łączę je na żądanie użytkownika. – Artyom

+0

Nie wyjaśniłeś, dlaczego potrzebujesz "memcpy near speedup", co wydaje się niewielką ilością danych. Być może powiesz nam, ile z tych stron musisz podawać na sekundę i jak duże są. –

+0

Załóżmy, że strony i kawałki są duże, a obciążenie jest ekstremalnie wysokie: . – Artyom

6

Instrukcja gzip mówi, że dwa pliki gzip mogą być łączone tak, jak próbowałeś.

http://www.gnu.org/software/gzip/manual/gzip.html#Advanced-usage

Wygląda więc na to, że inne narzędzia mogą być złamane. Jak widać w tym raporcie o błędzie. http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97263

Oprócz zgłaszania raportu o błędach u każdego z twórców przeglądarki, i mając nadzieję, że się do tego stosują, być może Twój program może przechowywać w pamięci podręcznej najczęstsze konkatenacje wymaganych danych.

Jak wspominają inni mogą być w stanie wykonać operację: http://www.gzip.org/zlib/rfc-gzip.html

a to wymaga CRC-32 od ostatecznego pliku nieskompresowanego. Wymagany rozmiar nieskompresowanego pliku można łatwo obliczyć, dodając długość poszczególnych pod-plików.

W dolnej części ostatniego linku znajduje się kod do obliczania działającego crc-32 o nazwie update_crc.

Obliczanie CRC nieskompresowanych plików przy każdym uruchomieniu procesu jest prawdopodobnie tańsze niż sam algorytm gzip.

+0

Mówiąc o bibliotekach .NET, osobiście zweryfikowałem, że ta biblioteka obsługuje wieloczęściowe pliki GZip: http://www.icsharpcode.net/opensource/sharpziplib/ – DenNukem