Рассчитать размер сообщения в кодировке Base 64 - PullRequest
26 голосов
/ 07 октября 2009

У меня есть двоичная строка, которую я кодирую в Base 64. Теперь мне нужно заранее узнать размер окончательной строки в кодировке Base 64.

Есть ли способ рассчитать это?

Что-то вроде:

BinaryStringSize - 64 КБ EncodedBinaryStringSize будет 127 КБ после кодирования.

О, код в C.

Спасибо.

Ответы [ 9 ]

31 голосов
/ 07 октября 2009

Если вы используете Base64 точно вправо , и это включает заполнение конца = символами, и вы разбиваете его на CR LF каждые 72 символа, ответ можно найти с помощью:

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;

В C вы также можете завершить с \0 -байтом, так что там будет дополнительный байт, и вы можете захотеть проверять длину в конце каждого кода по мере их написания, так что если вы просто ищите то, что вы передаете malloc(), вы можете предпочесть версию, которая тратит несколько байтов, чтобы упростить кодирование:

output_size = ((input_size * 4) / 3) + (input_size / 96) + 6;
24 голосов
/ 20 января 2010

ответ геокаря был близок, но иногда мог быть немного не верным.

На каждые 3 байта ввода выводится 4 байта. Если входной размер не кратен трем, мы должны добавить, чтобы он был один. В противном случае оставьте это в покое.

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

Разделите это на 3, затем умножьте на 4. Это наш общий размер вывода, включая отступы.

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

Как я уже сказал в своем комментарии, общий размер должен быть разделен на ширину линии перед удвоением, чтобы правильно учесть последнюю строку. В противном случае количество символов CRLF будет завышено. Я также предполагаю, что будет только пара CRLF, если строка будет состоять из 72 символов. Это включает в себя последнюю строку, но не если она меньше 72 символов.

newline_size = ((code_padded_size) / 72) * 2

Итак, соберите все вместе:

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;

Или сделать его немного более читабельным:

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;
6 голосов
/ 01 февраля 2012

Вот простая реализация на C (без модуля и тройных операторов) для необработанного кодированного base64 размера (со стандартным заполнением '='):

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

К этому вам потребуется добавить дополнительные издержки для CRLF, если это необходимо. Стандартное кодирование base64 (RFC 3548 или RFC 4648) допускает разрывы строк CRLF (длиной 64 или 76 символов), но не требует этого. Вариант MIME (RFC 2045) требует разрывов строк после каждых 76 символов.

Например, общая кодированная длина с использованием 76 символьных строк, основанная на приведенном выше:

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

См. Запись base64 в википедии для дополнительных вариантов.

3 голосов
/ 12 июня 2012

Я столкнулся с подобной ситуацией в python, и с использованием codecs.iterencode (text, "base64") правильный расчет был:

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
3 голосов
/ 08 октября 2009

Проверьте библиотеку b64 . Функция b64_encode2 () может дать максимальную оценку необходимого размера, если вы передадите NULL, так что вы можете с уверенностью выделить память, а затем снова вызвать пропускать буфер и заставить его выполнить преобразование. 1006 *

2 голосов
/ 24 июля 2012

Я думаю, что эта формула должна работать:

b64len = (size * 8 + 5) / 6
2 голосов
/ 07 октября 2009

Base 64 преобразует 3 байта в 4.

Если ваш набор битов не кратен 24 битам, вы должны заполнить его так, чтобы он был кратным 24 битам (3 байта).

1 голос
/ 30 ноября 2012
 if (inputSize == 0) return 0;

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

В этой формуле добавляется завершающий CRLF (MIME, rfc2045) тогда и только тогда, когда последняя строка не соответствует точно максимальной длине строки.

0 голосов
/ 07 октября 2009

Фактическая длина MIME-совместимых двоичных данных в кодировке base64 обычно составляет около 137% от исходной длины данных, хотя для очень коротких сообщений издержки могут быть намного выше из-за накладных расходов заголовков. Приблизительно конечный размер двоичных данных в кодировке base64 равен 1,37 от исходного размера данных + 814 байт (для заголовков).

Другими словами, вы можете приблизить размер декодированных данных по следующей формуле:

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

Источник: http://en.wikipedia.org/wiki/Base64

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...