2015-07-03 39 views
9

Ho un oggetto che sto cercando di comprimere. È di formaProblemi con la compressione in javascript

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

Gli array sono non più di 10-15 lunghezza, estremamente piccolo in confronto alle corde (sono html, approssimativamente 170k in lunghezza). Le stringhe sono di solito ripetute, o hanno enormi quantità di sovrapposizione. Quindi la mia intuizione mi dice che il valore compresso dovrebbe essere il valore di compressione di 1 stringa, più un piccolo extra.

I JSON.stringificare questo oggetto e provare a comprimere.

La maggior parte delle librerie di compressione ha fatto un brutto lavoro di compressione delle stringhe, dal momento che il server mi invia una versione compressa gzip di 77kb, so che può essere almeno così piccola.

gzip-js

lzma-js

fatto un buon lavoro fuori dai forse 15 librerie che ho provato.

Il problema è gzip-js è lineare nel numero di stringhe. Ma lzma lo fa correttamente, dove aumenta leggermente di dimensioni.

Lzma-js (livello 2) è molto lento, sfortunatamente (20s vs 1s gzip) durante la compressione di 7mbs (circa 30 ~ stringhe).

C'è una libreria di compressione qui, che è approssimativamente veloce come gzip, ma non si scala linearmente sulle stringhe di ripetizione?

+1

Puoi elencare quelli che hanno fatto un brutto lavoro che hai provato?Risolverà sicuramente il tempo di reset di noi per non dover fare lo stesso lavoro che hai già fatto. –

+0

Hai guardato le risposte a http://stackoverflow.com/questions/4570333/string-compression-in-javascript? I link di risposta più votati a questa pagina http://pieroxy.net/blog/pages/lz-string/index.html, che fa riferimento a qualche lib di compressione lz –

+0

Se hai del tempo puoi convertire i bit in immagine (ogni 3 bit come bixel) e salvarlo come immagine png lossless, le migliori prestazioni con una compressione molto buona –

risposta

1

Utilizzare il gzip-js lib con alto livello di impacco
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); 

ho trovato questo modo, come minimo, come dimensioni posible con durata normale

E per algoritmo di compressione LZ-based penso lz -string è più veloce di controllo
questo sul tuo campione di dati
https://github.com/pieroxy/lz-string

1

Pako è stato utile per me, provatelo:

Invece di utilizzare gli id ​​stringa utilizzare byteArrays, come è fatto here.

Get pako.js e si può decomprimere ByteArray in questo modo:

<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> 

esempio di Esecuzione: http://jsfiddle.net/9yH7M/

In alternativa si può base64 codificare la matrice prima di inviarlo su come l'Array prende un sacco di spese generali quando si invia come JSON o XML. Decodifica allo stesso modo:

// 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); 

Esecuzione esempio: http://jsfiddle.net/9yH7M/1/

Per funzioni più avanzate, leggere il pako API documentation.