2015-07-03 18 views
9

Mam obiekt, który próbuję kompresować. Jest formularzaProblemy z kompresją w javascript

[ 
    { 
    array 
    string 
    }, 
    { 
    array 
    string 
    }, 
    ... 
] 

Macierze są nie więcej niż 10-15 długości, bardzo małe w porównaniu do strun (są html, mniej więcej 170k długości). Ciągi są zwykle powtarzane lub mają ogromne nakładanie się. Więc moja intuicja mówi mi, że skompresowana wartość powinna być wartością kompresu o 1 łańcuchu, plus trochę więcej.

I JSON.stringuj ten obiekt i spróbuj go skompresować.

Większość bibliotek kompresujących źle radziła sobie z kompresją ciągów, ponieważ serwer wysyła do mnie skompresowaną gzip wersję 77kb, wiem, że może być co najmniej tak mały.

gzip-js

lzma-js

dobrą robotę Spośród może 15 bibliotek próbowałem.

Problem polega na tym, że gzip-js jest liniowy w liczbie łańcuchów. Ale lzma robi to poprawnie, gdzie tylko nieznacznie zwiększa rozmiar.

Lzma-js (poziom 2) jest bardzo wolny niestety (20s vs 1s gzip) podczas kompresowania 7mbs (około 30 ~ ciągów).

Czy istnieje biblioteka kompresująca, która jest mniej więcej tak szybka jak gzip, ale nie skaluje się liniowo na powtarzających się łańcuchach?

+1

Czy możesz wymienić te, które wykonały złą robotę, których próbujesz?Na pewno zaoszczędzi nam czasu, aby zrezygnować z tej samej pracy, którą już przeszedłeś. –

+0

Czy spojrzałeś na odpowiedzi na http://stackoverflow.com/questions/4570333/string-compression-in-javascript? Najlepiej ocenione łącze łączy się z tą stroną http://pieroxy.net/blog/pages/lz-string/index.html, która odwołuje się do kilku kompresji lib –

+0

Jeśli masz trochę czasu, możesz konwertować bity na obraz (co 3-bitowe jako bixel) i zapisać jako obraz bezstratny png, najlepsza wydajność z bardzo dobrym kompresorem –

Odpowiedz

1

Użyj gzip-js lib z wysokim poziomem kompresji
https://github.com/beatgammit/gzip-js

var gzip = require('gzip-js'), 
    options = { 
     level: 9, 
     name: 'hello-world.txt', 
     timestamp: parseInt(Date.now()/1000, 10) 
    }; 

// out will be a JavaScript Array of bytes 
var out = gzip.zip('Hello world', options); 

Znalazłem ten sposób co najmniej jak to możliwe wielkości z normalnego trwania

A dla algorytmu kompresji LZ opartej myślę LZ -string jest szybszy
sprawdź to na próbce danych
https://github.com/pieroxy/lz-string

1

Pako był dla mnie przydatny, spróbuj:

Zamiast używać ciągów ids użyj byteArrays, tak jak jest to robione here.

Get pako.js i można rozpakować tablicaBitowa tak:

<html> 
<head> 
<title>Gunzipping binary gzipped string</title> 
<script type="text/javascript" src="pako.js"></script> 
<script type="text/javascript"> 

// Get datastream as Array, for example: 
var charData = [31,139,8,0,0,0,0,0,0,3,5,193,219,13,0,16,16,4,192,86,214,151,102,52,33,110,35,66,108,226,60,218,55,147,164,238,24,173,19,143,241,18,85,27,58,203,57,46,29,25,198,34,163,193,247,106,179,134,15,50,167,173,148,48,0,0,0]; 

// Turn number array into byte-array 
var binData  = new Uint8Array(charData); 

// Pako magic 
var data  = pako.inflate(binData); 

// Convert gunzipped byteArray back to ascii string: 
var strData  = String.fromCharCode.apply(null, new Uint16Array(data)); 

// Output to console 
console.log(strData); 

</script> 
</head> 
<body> 
Open up the developer console. 
</body> 
</html> 

Running przykład: http://jsfiddle.net/9yH7M/

Alternatywnie można base64 zakodować tablicę przed wysłaniem go jako Array zajmuje dużo napowietrznych podczas wysyłania jako JSON lub XML. Dekodować także:

// Get some base64 encoded binary data from the server. Imagine we got this: 
var b64Data  = 'H4sIAAAAAAAAAwXB2w0AEBAEwFbWl2Y0IW4jQmziPNo3k6TuGK0Tj/ESVRs6yzkuHRnGIqPB92qzhg8yp62UMAAAAA=='; 

// Decode base64 (convert ascii to binary) 
var strData  = atob(b64Data); 

// Convert binary string to character-number array 
var charData = strData.split('').map(function(x){return x.charCodeAt(0);}); 

// Turn number array into byte-array 
var binData  = new Uint8Array(charData); 

// Pako magic 
var data  = pako.inflate(binData); 

// Convert gunzipped byteArray back to ascii string: 
var strData  = String.fromCharCode.apply(null, new Uint16Array(data)); 

// Output to console 
console.log(strData); 

Running przykład: http://jsfiddle.net/9yH7M/1/

Dla bardziej zaawansowanych funkcji, należy przeczytać pako API documentation.

Powiązane problemy