2009-10-07 43 views
25

Tengo una cadena binaria que estoy codificando en la Base 64. Ahora, necesito saber de antemano el tamaño de la cadena codificada en Base 64 final.Calcular el tamaño de un mensaje codificado en Base 64

¿Hay alguna manera de calcular eso?

Algo así como:

BinaryStringSize es 64Kb EncodedBinaryStringSize será 127KB después de la codificación.

Oh, el código está en C.

Gracias.

Respuesta

31

Si lo hace Base 64 exactly right, y que incluye el relleno final con = caracteres, y se rompe para arriba con un CR LF cada 72 caracteres, la respuesta se puede encontrar 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; 

En C, también puede terminar con un byte de \0, por lo que habrá un byte adicional allí, y es posible que desee verificar la longitud al final de cada código a medida que los escribe, de modo que si solo está buscando lo que pasa a malloc(), en realidad podría preferir una versión que desperdicia algunos bytes, para hacer la codificación más simple:

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

Los caracteres CRLF por 72 no están codificados en Base 64 en bruto; es solo una variante común. –

+0

Si pongo énfasis en "y" en "y lo rompes con ...", ¿eso lo dejaría más claro? – geocar

+0

Este cálculo de CRLF debe ser: crlfs_size = 2 + (2 * ((code_size + padding_size)/72)); El tamaño total se debe dividir por el ancho de línea antes de doblar para representar correctamente la última línea. De lo contrario, se sobreestimará el número de caracteres CRLF. Además, el 2 + puede no ser necesario si no hay un par CRLF final. – adzm

0

La longitud real de los datos binarios codificados en base64 que cumplen con MIME suele ser aproximadamente el 137% de la longitud de datos original, aunque para mensajes muy cortos la sobrecarga puede ser mucho mayor debido a la sobrecarga de los encabezados. Muy aproximadamente, el tamaño final de los datos binarios codificados en base64 es igual a 1,37 veces el tamaño de datos original + 814 bytes (para encabezados).

En otras palabras, se puede aproximar el tamaño de los datos decodificados con esta fórmula:

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

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

+0

Gracias. ¿Cómo pones eso en el código? – Uri

+0

genial, déjame revisarlo. – Uri

+0

gracias! Eso fue todo. – Uri

2

Base 64 transformadas de 3 bytes en 4.

Si' re set de bits no es un múltiplo de 24 bits, debe rellenarlo para que tenga un múltiplo de 24 bits (3 bytes).

+1

Entonces, longitud (Base-64) = 4 * (longitud (Binario) + 2)/3. Entonces pueden ser necesarias las nuevas líneas y el nulo final. –

+0

@Jonathan Leffler: Correcto. Y si se trata de un archivo adjunto MIME, se deben tener en cuenta todos los gastos generales de MIME. –

3

Revisa el b64 library. La función b64_encode2() puede dar una estimación máxima del tamaño requerido si pasa NULL, por lo que puede asignar memoria con certeza, y luego volver a llamar pasando el búfer y hacer la conversión.

24

La respuesta de geocar estuvo cerca, pero a veces podría estar un poco desajustada.

Hay 4 bytes de salida por cada 3 bytes de entrada. Si el tamaño de entrada no es un múltiplo de tres, debemos agregarlo para hacerlo uno. De lo contrario, déjalo en paz.

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

Dividir esta por 3, luego se multiplica por 4. Es decir nuestro tamaño total de la producción, incluyendo las protecciones.

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

Como dije en mi comentario, el tamaño total debe ser dividido por el ancho de la línea antes de doblar a explicar correctamente la última línea.De lo contrario, se sobreestimará el número de caracteres CRLF. También estoy suponiendo que solo habrá un par CRLF si la línea tiene 72 caracteres. Esto incluye la última línea, pero no si tiene menos de 72 caracteres.

newline_size = ((code_padded_size)/72) * 2 

Así que ponerlo todo junto:

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 para que sea un poco más fácil de leer:

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

¡Muy bien! Por cierto, ¿no son 76 caracteres, y no 72, para los CRLF? (según este RFC: https://tools.ietf.org/html/rfc4648) – Shlublu

+0

La longitud de la línea puede ser arbitraria, aunque el límite 76 está de hecho en ese RFC. 72 fue utilizado aquí simplemente porque eso es lo que se usó en el código que heredé. – adzm

5

Aquí es una aplicación simple en C (sin módulo y operadores trinarios) para tamaño codificado en base64 en bruto (con relleno '=' estándar):

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

Para eso tendrá que agregar cualquier sobrecarga adicional para CRLF si es necesario. La codificación base64 estándar (RFC 3548 o RFC 4648) permite saltos de línea CRLF (en 64 o 76 caracteres) pero no la requiere. La variante MIME (RFC 2045) requiere saltos de línea después de cada 76 caracteres.

Por ejemplo, la longitud total codificado utilizando 76 líneas de caracteres que construyen en lo anterior:

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

ver el base64 wikipedia entry para más variantes.

3

me encontré con una situación similar en pitón, y el uso de codecs.iterencode (texto, "base 64") el cálculo correcto 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

creo que esta fórmula debería funcionar:

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; 

Esta fórmula agrega una terminación CRLF (MIME, rfc2045) si y solo si la última línea no cabe exactamente en la longitud de línea máxima.

Cuestiones relacionadas