2009-10-07 20 views
25

Ho una stringa binaria che sto codificando in Base 64. Ora, ho bisogno di sapere prima che la dimensione della stringa codificata Base 64 finale sarà.Calcola la dimensione in un messaggio con codifica Base 64

C'è un modo per calcolarlo?

Qualcosa di simile:

BinaryStringSize è 64Kb EncodedBinaryStringSize verrà 127KB dopo la codifica.

Oh, il codice è in C.

Grazie.

risposta

31

Se lo fai Base64 exactly right, e che comprende imbottitura alla fine con = personaggi, e si rompe in su con un CR LF ogni 72 caratteri, la risposta può essere trovata con:

code_size = ((input_size * 4)/3); 
padding_size = (input_size % 3) ? (3 - (input_size % 3)) : 0; 
crlfs_size = 2 + (2 * (code_size + padding_size)/72); 
total_size = code_size + padding_size + crlfs_size; 

In C, è può anche terminare con un \0 -byte, quindi ci sarà un byte extra lì, e potresti voler controllare la lunghezza alla fine di ogni codice mentre li scrivi, quindi se stai solo cercando quello che passi a malloc(), si potrebbe effettivamente preferire una versione che spreca pochi byte, al fine di semplificare la codifica:

output_size = ((input_size * 4)/3) + (input_size/96) + 6; 
+4

I caratteri CRLF-per-72 non sono codificati in Base 64; è solo una variante comune. –

+0

Se metto l'accento su "e" su "e lo interrompi con ...", questo lo renderebbe più chiaro? – geocar

+0

Questo calcolo CRLF dovrebbe essere: crlfs_size = 2 + (2 * ((code_size + padding_size)/72)); La dimensione totale deve essere divisa per la larghezza della linea prima del raddoppio per rappresentare correttamente l'ultima riga. Altrimenti il ​​numero di caratteri CRLF sarà sovrastimato. Anche il 2 + potrebbe non essere necessario se non c'è una coppia CRLF finale. – adzm

0

La lunghezza effettiva dei dati binari codificati in base64 conformi a MIME è di solito circa il 137% della lunghezza dei dati originali, sebbene per i messaggi molto brevi il sovraccarico possa essere molto più alto a causa del sovraccarico delle intestazioni. Molto approssimativamente, la dimensione finale dei dati binari con codifica Base64 è pari a 1.37 volte la dimensione dei dati originali + 814 byte (per le intestazioni).

In altre parole, si può approssimare la dimensione dei dati decodificati con questa formula:

BytesNeededForEncoding = (string_length(base_string) * 1.37) + 814; 
BytesNeededForDecoding = (string_length(encoded_string) - 814)/1.37; 

Fonte: http://en.wikipedia.org/wiki/Base64

+0

Grazie. Come lo metti in codice? – Uri

+0

fantastico, lasciami andare a controllare. – Uri

+0

grazie! Era così. – Uri

2

Base 64 trasforma 3 byte in 4.

Se si' il set di bit non è un multiplo di 24 bit, è necessario eseguire il pad out in modo che abbia un multiplo di 24 bit (3 byte).

+1

Quindi, length (Base-64) = 4 * (length (Binary) + 2)/3. Quindi newlines e lo zero finale potrebbero dover essere considerati. –

+0

@ Jonathan Leffler: corretto. E se si tratta di un allegato MIME, tutti i costi generali MIME devono essere presi in considerazione. –

3

Verificare il b64 library. La funzione b64_encode2() può fornire una stima massima della dimensione richiesta se si passa NULL, quindi è possibile allocare la memoria con certezza, quindi richiamare nuovamente il buffer e fare eseguire la conversione.

24

La risposta di geocar era vicina, ma a volte poteva essere leggermente ridotta.

Ci sono 4 byte in uscita per ogni 3 byte di input. Se la dimensione di input non è un multiplo di tre, dobbiamo aggiungere per renderla una. Altrimenti lascia stare.

input_size + ((input_size % 3) ? (3 - (input_size % 3)) : 0) 

dividere questo da 3, poi moltiplicare per 4. Questa è la nostra dimensione totale in uscita, o imbottitura.

code_padded_size = ((input_size + ((input_size % 3) ? (3 - (input_size % 3)) : 0))/3) * 4 

Come ho detto nel mio commento, la dimensione totale deve essere diviso per la larghezza della linea prima del raddoppio di spiegare correttamente per l'ultima riga.Altrimenti il ​​numero di caratteri CRLF sarà sovrastimato. Suppongo anche che ci sarà solo una coppia CRLF se la linea è di 72 caratteri. Questo include l'ultima riga, ma non se è inferiore a 72 caratteri.

newline_size = ((code_padded_size)/72) * 2 

Così si può mettere tutto insieme:

unsigned int code_padded_size = ((input_size + ((input_size % 3) ? (3 - (input_size % 3)) : 0))/3) * 4; 
unsigned int newline_size = ((code_padded_size)/72) * 2; 

unsigned int total_size = code_padded_size + newline_size; 

O per renderlo un po 'più leggibile:

unsigned int adjustment = ((input_size % 3) ? (3 - (input_size % 3)) : 0); 
unsigned int code_padded_size = ((input_size + adjustment)/3) * 4; 
unsigned int newline_size = ((code_padded_size)/72) * 2; 

unsigned int total_size = code_padded_size + newline_size; 
+0

Davvero bello! A proposito, non sono 76 caratteri, e non 72, per i CRLF? (come da RFC: https://tools.ietf.org/html/rfc4648) – Shlublu

+0

La lunghezza della linea può essere arbitraria, sebbene il limite 76 sia effettivamente in quella RFC. 72 è stato usato qui solo perché è quello che è stato usato nel codice che ho ereditato. – adzm

5

Ecco un'implementazione C semplice (senza modulo e operatori trinario) per dimensione codificata base64 grezza (con riempimento standard = =):

int output_size; 
output_size = ((input_size - 1)/3) * 4 + 4; 

A tale scopo sarà necessario aggiungere eventuali overhead aggiuntivi per CRLF, se necessario. La codifica base64 standard (RFC 3548 o RFC 4648) consente interruzioni di riga CRLF (a 64 o 76 caratteri) ma non lo richiede. La variante MIME (RFC 2045) richiede interruzioni di riga ogni 76 caratteri.

Ad esempio, la lunghezza totale codificato usando 76 linee di carattere costruzione di quanto sopra:

int final_size; 
final_size = output_size + (output_size/76) * 2; 

vedere i base64 wikipedia entry per altri modelli.

3

mi sono imbattuto in una situazione simile in Python, e usando codecs.iterencode (testo, "base64"), il calcolo corretta era:

adjustment = 3 - (input_size % 3) if (input_size % 3) else 0 
code_padded_size = ((input_size + adjustment)/3) * 4 
newline_size = ((code_padded_size)/76) * 1 
return code_padded_size + newline_size 
1

penso che questa formula dovrebbe funzionare:

b64len = (size * 8 + 5)/6 
1
if (inputSize == 0) return 0; 

int size = ((inputSize - 1)/3) * 4 + 4; 
int nlines = (size - 1)/ maxLine + 1; 
return size + nlines * 2; 

Questa formula aggiunge CRLF (MIME, rfc2045) di terminazione se e solo se l'ultima riga non si adatta esattamente alla lunghezza massima della linea.

Problemi correlati