ファイルを塊でbase64エンコードすることは可能ですか?

私は、base64で巨大な入力ファイルをエンコードしようとしていて、テキスト出力ファイルで終わります。入力ファイルをビット単位でエンコードすることが可能かどうか、またはエンコードする必要があるかどうかを調べようとしていますすぐに事。

これは、AS/400(iSeries)で行われます。私は自分のベース64エンコーディングルーチン(RPGで書かれています)を使っています。これはうまく動作し、サイズ制限の場合ではありませんでした。

12

3 答え

ビットごと ではなく、 3バイトずつ、または3バイトの倍数で実行できます

つまり、あなたの入力ファイルを3バイトの倍数である "チャンク"で分割すると、チャンクを別々にエンコードして、結果のB64エンコードされたピースを一緒にまとめることができます(対応するordeのもちろん、最後のchuinkは3バイトの倍数である必要はありません。サイズのモジュロ3の値に応じて、対応するB64値にはこれらのパディング文字(通常は等号)がいくつかありますが、それは問題ありません。そのような詰め物がある(そして必要とする)唯一のものであるからです。

デコード方向では、B64でエンコードされたデータを4バイトの倍数に分割する必要がある点を除いて、同じ考え方です。それらをパラレル/個別に希望どおりにデコードし、デコードされた部分を一緒に(同じ順序で)追加して元のデータを再作成します。

例:

"File" contents = "Never argue with the data." (Jimmy Neutron).
Straight encoding = Ik5ldmVyIGFyZ3VlIHdpdGggdGhlIGRhdGEuIiAoSmltbXkgTmV1dHJvbik=

Now, in chunks:
"Never argue     -->     Ik5ldmVyIGFyZ3Vl
with the         -->        IHdpdGggdGhl
data." (Jimmy Neutron) --> IGRhdGEuIiAoSmltbXkgTmV1dHJvbik=

あなたがその順序でピースを見るので、3つのコード化されたチャンクは、ファイル全体に対して生成されたコードと同じです。

デコードは、4バイトの倍数であれば、任意のチャンクサイズで同様に行われます。エンコーディングに使用されるサイズの間には、どんな種類の対応も絶対に必要ありません。 (ただし、各方向(たとえば300と400)で単一のサイズに標準化することで、より均一で管理しやすくなります。

26
追加された
特定のバッファサイズ(3の倍数ではありません)を使用する必要があるため、掘り下げなければなりませんでした。一度私の脳のおならが消えたら、私はちょうどバッファサイズを変更しました。だから本当に、私はばかだ。そして、誰もが明らかに "バッファサイズを3の倍数にする"という質問に答えても、最初のものだったので、チェックマークがついています。ありがとう!
追加された 著者 roryhewitt,

うーん、Base64変換を自分で書いたのであれば、明らかなことに気づいたはずです.3オクテットの各シーケンスは、base64では4文字で表されます。

したがって、base64データを4文字の倍数に分割することができ、これらのチャンクを元のビットに戻すことができます。

キャラクターファイルとバイトファイルがAS/400上でどのように扱われるかはわかりませんが、両方の概念がある場合は非常に簡単です。

  • 各行の長さに制限のあるテキストファイルですか?
  • テキストファイルは行指向ですか、それとも単に文字ストリームですか?
  • 1バイトに何ビットありますか?
  • 最後に埋め込まれたバイトファイルなので、ディスクセクタ全体にまたがるファイルしか作成できません。

これらすべての質問に答えることができれば、どんな困難が残っていますか?

2
追加された
なし - 私はばかだった:(
追加された 著者 roryhewitt,

任意のバイトストリームをチャンクに分割するのは簡単な作業です。

任意のバイトのチャンクを問題なくbase64することができます。

あなたが直面している問題は、チャンク(3バイトの倍数)に特定の要件を置かない限り、base64でエンコードされたチャンクのシーケンスが実際の出力と異なることです。

C#では、これはあなたがそれをゆっくりと行うことができる1つ(ちょっとした)方法です。実行は実際にはstring.Concatが呼び出されるまで延期されるので、チャンクされた文字列で必要な処理を行うことができます。 (これをLINQPadに接続すると出力が表示されます)

void Main()
{
    var data = "lorum ipsum etc lol this is an example!!";
    var bytes = Encoding.ASCII.GetBytes(data);
    var testFinal = Convert.ToBase64String(bytes);

    var chunkedBytes = bytes.Chunk(3);
    var base64chunks = chunkedBytes.Select(i => Convert.ToBase64String(i.ToArray()));
    var final = string.Concat(base64chunks);

    testFinal.Dump(); //出力
    final.Dump(); //出力
}
public static class Extensions
{
    public static IEnumerable> Chunk(this IEnumerable list, int chunkSize)
    {
        while(list.Take(1).Count() > 0)
        {
            yield return list.Take(chunkSize);
            list = list.Skip(chunkSize);
        }
    }
}

出力

bG9ydW0gaXBzdW0gZXRjIGxvbCB0aGlzIGlzIGFuIGV4YW1wbGUhIQ==
bG9ydW0gaXBzdW0gZXRjIGxvbCB0aGlzIGlzIGFuIGV4YW1wbGUhIQ==
2
追加された