185

base64wikiを読んだ...

私は式がどのように機能しているかを理解しようとしています:

長さが。の文字列を指定するnと、base64の長さは次のようになります。ここに画像の説明を入力してください

これは:4*Math.Ceiling(((double)s.Length/3)))

%4==0base64の長さは、デコーダーが元のテキストの長さを認識できるようにするためのものでなければならないことはすでに知っています。

シーケンスのパディングの最大数は、=または==です。

wiki:入力バイトあたりの出力バイト数は約4/3(33%のオーバーヘッド)

質問:

上記の情報は、出力の長さで どのここに画像の説明を入力してくださいように解決されますか?

4

15 に答える 15

255

各文字は6ビット(log2(64) = 6)を表すために使用されます。

したがって、を表すために4文字が使用され4 * 6 = 24 bits = 3 bytesます。

したがって、バイト4*(n/3)を表すにはcharが必要nであり、これは4の倍数に切り上げる必要があります。

4の倍数に切り上げた結果の未使用のパディング文字の数は、明らかに0、1、2、または3になります。

于 2012-11-14T12:29:05.277 に答える
77

4 * n / 3パッドなしの長さを提供します。

また、パディングの場合は4の最も近い倍数に切り上げます。4は2の累乗であるため、ビット単位の論理演算を使用できます。

((4 * n / 3) + 3) & ~3
于 2015-08-21T12:19:26.667 に答える
32

参考までに、Base64エンコーダーの長さの式は次のとおりです。

Base64エンコーダーの長さの式

nあなたが言ったように、データのバイトを与えられたBase64エンコーダーは4n/3Base64文字の文字列を生成します。言い換えると、3バイトのデータごとに4つのBase64文字になります。編集コメントは、私の前のグラフィックがパディングを考慮していなかったことを正しく指摘しています。パディングの正しい式はです 4(Ceiling(n/3))

ウィキペディアの記事は、その例でASCII文字列Man がBase64文字列にどのようにエンコードされているかを正確に示しています。TWFu入力文字列のサイズは3バイト(24ビット)であるため、式は出力が4バイト(または32ビット)の長さになることを正しく予測しますTWFu。このプロセスでは、6ビットごとのデータが64のBase64文字の1つにエンコードされるため、24ビットの入力を6で割ると4つのBase64文字になります。

コメントで、エンコーディングのサイズを尋ね123456ます。その文字列のすべての文字のサイズが1バイト(8ビット)であることを念頭に置いて(ASCII / UTF8エンコードを想定)、6バイト(48ビット)のデータをエンコードしています。式によると、出力の長さはであると予想されます(6 bytes / 3 bytes) * 4 characters = 8 characters

Base64123456エンコーダーに入れると、MTIzNDU2予想どおり、8文字の長さのが作成されます。

于 2013-07-25T17:26:20.253 に答える
19

整数

浮動小数点演算、丸め誤差などを使用したくないため、通常、doubleは使用しません。これらは必要ありません。

このため、天井の除算を実行する方法を覚えておくことをお勧めします。doubleでは、次のceil(x / y)ように書くことができます(x + y - 1) / y(負の数は避けますが、オーバーフローに注意してください)。

読みやすい

読みやすさを重視する場合は、もちろん次のようにプログラムすることもできます(Javaの例では、もちろんCの場合はマクロを使用できます)。

public static int ceilDiv(int x, int y) {
    return (x + y - 1) / y;
}

public static int paddedBase64(int n) {
    int blocks = ceilDiv(n, 3);
    return blocks * 4;
}

public static int unpaddedBase64(int n) {
    int bits = 8 * n;
    return ceilDiv(bits, 6);
}

// test only
public static void main(String[] args) {
    for (int n = 0; n < 21; n++) {
        System.out.println("Base 64 padded: " + paddedBase64(n));
        System.out.println("Base 64 unpadded: " + unpaddedBase64(n));
    }
}

インライン化

パッド入り

3バイト(またはそれ以下)ごとに一度に4文字のブロックが必要であることがわかっています。したがって、式は次のようになります(x=nおよびy=3の場合)。

blocks = (bytes + 3 - 1) / 3
chars = blocks * 4

または組み合わせて:

chars = ((bytes + 3 - 1) / 3) * 4

コンパイラはを最適化する3 - 1ので、読みやすさを維持するためにこのままにしておきます。

パッドなし

パッドなしのバリアントはあまり一般的ではありません。このため、6ビットごとに切り上げた文字が必要であることを覚えています。

bits = bytes * 8
chars = (bits + 6 - 1) / 6

または組み合わせて:

chars = (bytes * 8 + 6 - 1) / 6

ただし、(必要に応じて)2で割ることはできます。

chars = (bytes * 4 + 3 - 1) / 3

読めない

コンパイラが最終的な最適化を行うことを信頼していない場合(または同僚を混乱させたい場合):

パッド入り

((n + 2) / 3) << 2

パッドなし

((n << 2) | 2) / 3

つまり、2つの論理的な計算方法があり、本当に必要な場合を除いて、分岐、ビット演算、モジュロ演算は必要ありません。

ノート:

  • 明らかに、ヌル終了バイトを含めるには、計算に1を追加する必要がある場合があります。
  • Mimeの場合、行末文字などの可能性に注意する必要がある場合があります(他の回答を探してください)。
于 2017-07-30T15:19:40.203 に答える
13

(簡潔でありながら完全な派生を与えるために。)

すべての入力バイトには8ビットがあるため、n個の入力バイトに対して次のようになります。

n ×8入力ビット

6ビットごとが出力バイトなので、次のようになります。

ceiln ×8/6)=  ceiln ×4/3)出力バイト

これはパディングなしです。

パディングを使用して、これを4の倍数の出力バイトに切り上げます。

ceilceiln ×4/3)/ 4)×4 =  ceiln ×4/3/4)×4 =  ceiln / 3)×4出力バイト

最初の同等性については、ネストされた部門(Wikipedia)を参照してください。

整数演算を使用すると、ceiln / m)はn + m – 1)div mとして計算できるため、次のようになります。

n * 4 + 2)div3パディングなし

n + 2)div 3 * 4(パディングあり)

説明のために:

 n   with padding    (n + 2) div 3 * 4    without padding   (n * 4 + 2) div 3 
------------------------------------------------------------------------------
 0                           0                                      0
 1   AA==                    4            AA                        2
 2   AAA=                    4            AAA                       3
 3   AAAA                    4            AAAA                      4
 4   AAAAAA==                8            AAAAAA                    6
 5   AAAAAAA=                8            AAAAAAA                   7
 6   AAAAAAAA                8            AAAAAAAA                  8
 7   AAAAAAAAAA==           12            AAAAAAAAAA               10
 8   AAAAAAAAAAA=           12            AAAAAAAAAAA              11
 9   AAAAAAAAAAAA           12            AAAAAAAAAAAA             12
10   AAAAAAAAAAAAAA==       16            AAAAAAAAAAAAAA           14
11   AAAAAAAAAAAAAAA=       16            AAAAAAAAAAAAAAA          15
12   AAAAAAAAAAAAAAAA       16            AAAAAAAAAAAAAAAA         16

最後に、MIME Base64エンコーディングの場合、76出力バイトごとに2つの追加バイト(CR LF)が必要であり、終了改行が必要かどうかに応じて切り上げまたは切り下げられます。

于 2020-02-05T00:02:54.313 に答える
6

エンコードされたBase64ファイルの元のサイズをKB単位の文字列として計算する関数は次のとおりです。

private Double calcBase64SizeInKBytes(String base64String) {
    Double result = -1.0;
    if(StringUtils.isNotEmpty(base64String)) {
        Integer padding = 0;
        if(base64String.endsWith("==")) {
            padding = 2;
        }
        else {
            if (base64String.endsWith("=")) padding = 1;
        }
        result = (Math.ceil(base64String.length() / 4) * 3 ) - padding;
    }
    return result / 1000;
}
于 2017-08-17T09:58:40.647 に答える
5

与えられた答えは、元の質問のポイント、つまり長さnバイトの与えられたバイナリ文字列のbase64エンコーディングに適合するために割り当てる必要のあるスペースの量を見逃していると思います。

答えは(floor(n / 3) + 1) * 4 + 1

これには、パディングと終了ヌル文字が含まれます。整数演算を行う場合は、フロア呼び出しは必要ない場合があります。

パディングを含め、base64文字列は、部分的なチャンクを含め、元の文字列の3バイトのチャンクごとに4バイトを必要とします。文字列の最後に1バイトまたは2バイト余分に追加すると、パディングが追加されたときにbase64文字列で4バイトに変換されます。非常に特殊な用途がない限り、通常は等しい文字であるパディングを追加するのが最善です。Cのヌル文字に追加のバイトを追加しました。これがないASCII文字列は少し危険であり、文字列の長さを個別に運ぶ必要があるためです。

于 2014-03-23T15:38:09.063 に答える
3

他の誰もが代数式について議論している間、私はむしろBASE64自体を使用して次のように伝えたいと思います。

$ echo "Including padding, a base64 string requires four bytes for every three-byte chunk of the original string, including any partial chunks. One or two bytes extra at the end of the string will still get converted to four bytes in the base64 string when padding is added. Unless you have a very specific use, it is best to add the padding, usually an equals character. I added an extra byte for a null character in C, because ASCII strings without this are a little dangerous and you'd need to carry the string length separately."| wc -c

525

$ echo "Including padding, a base64 string requires four bytes for every three-byte chunk of the original string, including any partial chunks. One or two bytes extra at the end of the string will still get converted to four bytes in the base64 string when padding is added. Unless you have a very specific use, it is best to add the padding, usually an equals character. I added an extra byte for a null character in C, because ASCII strings without this are a little dangerous and you'd need to carry the string length separately." | base64 | wc -c

710

したがって、4つのbase64文字で表される3バイトの式は正しいようです。

于 2016-05-29T01:12:56.317 に答える
3

Cを話すすべての人のために、これらの2つのマクロを見てください。

// calculate the size of 'output' buffer required for a 'input' buffer of length x during Base64 encoding operation
#define B64ENCODE_OUT_SAFESIZE(x) ((((x) + 3 - 1)/3) * 4 + 1) 

// calculate the size of 'output' buffer required for a 'input' buffer of length x during Base64 decoding operation
#define B64DECODE_OUT_SAFESIZE(x) (((x)*3)/4) 

ここから撮影。

于 2019-09-30T10:58:21.793 に答える
3

他の回答には簡略化された式が表示されません。ロジックはカバーされていますが、組み込みで使用するための最も基本的なフォームが必要でした。

  Unpadded = ((4 * n) + 2) / 3

  Padded = 4 * ((n + 2) / 3)

注:パディングされていないカウントを計算するときは、整数の除算を切り上げます。つまり、この場合は+2である除数-1を追加します。

于 2020-06-22T06:46:29.600 に答える
1

正しい式は次のようになります。

n64 = 4 * (n / 3) + (n % 3 != 0 ? 4 : 0)
于 2015-03-07T00:12:11.593 に答える
1

n%3がゼロでない場合、これは正確な答えだと思います。

    (n + 3-n%3)
4 * ---------
       3

Mathematicaバージョン:

SizeB64[n_] := If[Mod[n, 3] == 0, 4 n/3, 4 (n + 3 - Mod[n, 3])/3]

楽しむ

GI

于 2016-06-03T13:30:26.130 に答える
1

javascriptでの簡単な実装

function sizeOfBase64String(base64String) {
    if (!base64String) return 0;
    const padding = (base64String.match(/(=*)$/) || [])[1].length;
    return 4 * Math.ceil((base64String.length / 3)) - padding;
}
于 2018-08-17T11:13:25.563 に答える
1

JSで@PedroSilvaソリューションを実現することに関心のある人がいる場合は、これと同じソリューションを移植しました。

const getBase64Size = (base64) => {
  let padding = base64.length
    ? getBase64Padding(base64)
    : 0
  return ((Math.ceil(base64.length / 4) * 3 ) - padding) / 1000
}

const getBase64Padding = (base64) => {
  return endsWith(base64, '==')
    ? 2
    : 1
}

const endsWith = (str, end) => {
  let charsFromEnd = end.length
  let extractedEnd = str.slice(-charsFromEnd)
  return extractedEnd === end
}
于 2019-04-12T08:21:08.777 に答える
0

Windowsでは、mime64サイズのバッファーのサイズを見積もりたかったのですが、すべての正確な計算式が機能しませんでした。最終的に、次のような近似式になりました。

Mine64文字列割り当てサイズ(概算)=(((4 *((バイナリバッファサイズ)+ 1))/ 3)+ 1)

したがって、最後の+1-これはASCIIゼロに使用されます-最後の文字はゼロ終了を格納するために割り当てる必要があります-しかし、なぜ「バイナリバッファサイズ」は+1です-mime64終了文字があるのではないかと思いますか?または、これはアライメントの問題である可能性があります。

于 2016-02-27T07:48:20.550 に答える