2009-05-30 11 views
5

Sto creando qualcosa che include un servizio di caricamento file di sorta, e ho bisogno di memorizzare i dati compressi con la funzione compress() di zlib. Lo mando su Internet già compresso, ma ho bisogno di conoscere la dimensione del file non compresso sul server remoto. C'è un modo per capire queste informazioni senza decomprimere() prima i dati sul server, solo per l'efficienza? Ecco come lo sto facendo ora, ma se c'è una scorciatoia mi piacerebbe prenderlo.Ottieni la dimensione dei dati non compressi in zlib?

A proposito, perché si chiama uncompress? Mi sembra piuttosto terribile, ho sempre pensato che sarebbe stato decompresso ...

+1

La mia ipotesi sul motivo per cui si chiama uncompress è a causa di un programma chiamato pkzip che è apparso nei primi anni '90. C'era un programma simulato chiamato pkunzip. Penso che il "un" sia bloccato. http://en.wikipedia.org/wiki/PKZIP – gradbot

+0

Ulteriori ricerche su wikipedia suggeriscono che si è trattato di una causa che ha costretto a cambiare nome. "Katz ha cambiato i nomi delle sue utilità in PKPAK e PKUNPAK." Più tardi hanno creato la propria versione chiamata zip. "Il nome" zip "(che significa" velocità ") è stato suggerito dall'amico di Katz, Robert Mahoney: volevano insinuare che il loro prodotto fosse più veloce di ARC e altri formati di compressione del tempo." Quindi zip e unzip è nato. – gradbot

+0

Ah-hah. Interessante :) – AriX

risposta

3

Il formato zlib non ha un campo per il formato originale in ingresso, quindi dubito sarai in grado di farlo senza simulare una decompressione dei dati. Lo gzip format ha un campo "input size" (ISIZE), che è possibile utilizzare, ma forse si desidera evitare di modificare il formato di compressione o di inviare i client alle dimensioni del file.

Ma anche se si utilizza un formato diverso, se non ci si fida dei client, sarà comunque necessario eseguire un controllo più costoso per assicurarsi che i dati non compressi corrispondano alle dimensioni specificate dal client. In questo caso, ciò che puoi fare è rendere il processo uncompress-to-/dev/null meno costoso, assicurandoti che zlib non scriva i dati di output da nessuna parte, poiché vuoi solo conoscere la dimensione non compressa.

+0

Grazie. Non avevo pensato di decomprimere in/dev/null :) – AriX

4

Ne dubito. Non credo che questo sia qualcosa che le librerie zlib sottostanti forniscono dalla memoria (anche se sono passati 7 o 8 anni da quando l'ho usato, i documenti aggiornati non sembrano indicare che questa funzione è stata aggiunta).

Una possibilità potrebbe essere quella di trasferire un altro file che conteneva la dimensione non compressa (ad esempio, il trasferimento sia file.zip e file.zip.size), ma che sembra pieno di pericoli, soprattutto se si ottiene la dimensione sbagliata.

Un'altra alternativa è, se il server che non comprime è costoso nel tempo ma non deve essere eseguito immediatamente, per eseguirlo in un'attività in background con priorità più bassa (come con nice in Linux). Ma ancora, ci possono essere degli svantaggi se il correttore di dimensioni inizia a essere eseguito (troppi caricamenti in arrivo).

E tendo a pensare di decompressione in termini di "decompressione esplosiva", non è un buon termine da usare :-)

+0

Sì, potrei sempre dire al server qual è la dimensione, ma gli utenti potrebbero facilmente sfruttarlo, e davvero non voglio fare una sorta di complicato controllo dell'hash o altro. – AriX

3

Se stai caricando utilizzando il formato "compresso" raw, non avrai informazioni sulla dimensione dei dati che vengono caricati. La Pax è corretta a questo proposito.
È possibile memorizzarlo come intestazione a 4 byte all'inizio del buffer di compressione, presupponendo che la dimensione del file non superi i 4 GB.
po 'di codice C come esempio:

uint8_t *compressBuffer = calloc(bufsize + sizeof (uLongf), 0); 
uLongf compressedSize = bufsize; 
*((uLongf *)compressBuffer) = filesize; 
compress(compressBuffer + sizeof (uLongf), &compressedSize, sourceBuffer, bufsize); 

quindi si invia il compressBuffer completa della dimensione compressedSize + sizeof (uLongf). Quando si riceve sul lato server, è possibile utilizzare il seguente codice per ottenere i dati indietro:

// data is in compressBuffer, assume you already know compressed size. 
uLongf originalSize = *((uLongf *)compressBuffer); 
uint8_t *realCompressBuffer = compressBuffer + sizeof (uLongf); 

Se non vi fidate del client per inviare il formato corretto allora si avrà bisogno di eseguire una sorta di non compresso controllo dei dati sulla dimensione del server. Il suggerimento di usare uncompress su/dev/null è ragionevole.
Se si sta caricando un file .zip, contiene una directory che indica la dimensione del file quando non è compresso. Queste informazioni sono incorporate nel formato di file, anche se questo è soggetto a client dannosi.

Problemi correlati