web-dev-qa-db-ja.com

Base 64エンコードメッセージのサイズを計算する

私はBase 64でエンコードしているバイナリ文字列を持っています。ここで、Base 64でエンコードされた最終的な文字列のサイズを事前に知る必要があります。

それを計算する方法はありますか?

何かのようなもの:

BinaryStringSizeは64Kbです。EncodedBinaryStringSizeはエンコード後に127Kbになります。

ああ、コードはCです。

ありがとう。

26
Uri

Base64 exactlyright を実行し、_=_文字で末尾を埋め込んで、それを壊した場合72文字ごとに_CR LF_を使用すると、答えは次のように見つかります:

_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_- byteで終了することもできるので、そこに余分なバイトがあり、コードを書くときにすべてのコードの最後で長さをチェックすることをお勧めします。 malloc()に渡すものを探すだけでも、コーディングを簡単にするために、実際には数バイトを無駄にするバージョンを好むかもしれません。

_output_size = ((input_size * 4) / 3) + (input_size / 96) + 6;
_
31
geocar

geocarの答えは近いものでしたが、時々少しずれている可能性があります。

入力の3バイトごとに4バイトの出力があります。入力サイズが3の倍数でない場合は、1にするために追加する必要があります。それ以外の場合はそのままにしておきます。

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

コメントで述べたように、最後の行を適切に説明するには、合計サイズを2倍にする前に行幅で割る必要があります。そうしないと、CRLF文字の数が過大評価されます。また、行が72文字の場合、CRLFペアのみが存在すると想定しています。これには最後の行が含まれますが、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;
24
adzm

以下は、base64でエンコードされた未加工サイズ(標準の「=」パディング付き)の単純なC実装(モジュラス演算子および3項演算子なし)です。

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 wikipedia entry を参照してください。

6
kanaka

私は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
brettcvz

b64ライブラリ を確認してください。関数 b64_encode2() は、NULLを渡した場合に必要なサイズの最大推定値を提供できるため、確実にメモリを割り当ててから、バッファを渡して再度呼び出し、それを実行させることができます。変換。

3
dcw

私はこの式がうまくいくと思います:

b64len = (size * 8 + 5) / 6
2
Kevin Hsu

Base 64は3バイトを4に変換します。

ビットのセットが24ビットの倍数にならない場合は、24ビットの倍数(3バイト)になるようにパディングする必要があります。

2
S.Lott
 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)を追加します。

1
arnon

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

0
Gary Willoughby