46

単純な文字列をbase64との間でエンコード/デコードする方法を知っています。

しかし、データが既にFileStreamオブジェクトに書き込まれている場合、どうすればよいでしょうか。以前に保存された元のデータではなく、FileStream オブジェクトにしかアクセスできないとしましょう。FileStream をファイルにフラッシュする前に、 FileStream を base64にエンコードするにはどうすればよいですか。

FileStream をファイルに書き込んだ後、ファイルを開いてエンコード/デコードすることもできますが、2 つのファイル操作を次々に実行することなく、これをすべて 1 つのステップで実行したいと考えています。ファイルが大きくなる可能性があり、少し前に保存した直後に再度読み込み、エンコード、保存するのに 2 倍の時間がかかります。

多分あなたの誰かがより良い解決策を知っていますか?たとえば、FileStream を文字列に変換し、文字列をエンコードしてから、文字列を FileStream に戻すことはできますか?

4

6 に答える 6

35

4GB を超えるサイズのファイルなどの大きなストリームを処理する場合、ファイルを ( として) メモリにロードしたくありません。Byte[]これは、非常に遅いだけでなく、64 ビット プロセスでもクラッシュが発生する可能性があるためです。Byte[]2GB (または の場合は 4GB gcAllowVeryLargeObjects) を超えることはできません。

さいわい、.NETToBase64Transformには、ストリームをチャンクで処理する というきちんとしたヘルパーがあります。何らかの理由で Microsoft がそれを入れて(で使用するために)System.Security.Cryptography実装しますが、暗号化タスクを実行していないという理由だけでそれを無視します (「他の名前のバラ...」)。ICryptoTransformCryptoStream

CryptoStream次のように使用します。

using System.Security.Cryptography;
using System.IO;

//

using( FileStream   inputFile    = new FileStream( @"C:\VeryLargeFile.bin", FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 1024 * 1024, useAsync: true ) ) // When using `useAsync: true` you get better performance with buffers much larger than the default 4096 bytes.
using( CryptoStream base64Stream = new CryptoStream( inputFile, new ToBase64Transform(), CryptoStreamMode.Read ) )
using( FileStream   outputFile   = new FileStream( @"C:\VeryLargeBase64File.txt", FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 1024 * 1024, useAsync: true ) )
{
    await base64Stream.CopyToAsync( outputFile ).ConfigureAwait(false);
}
于 2019-09-06T10:43:20.140 に答える
14

あなたはそのようなことを試すことができます:

    public Stream ConvertToBase64(Stream stream)
    {
        Byte[] inArray = new Byte[(int)stream.Length];
        Char[] outArray = new Char[(int)(stream.Length * 1.34)];
        stream.Read(inArray, 0, (int)stream.Length);
        Convert.ToBase64CharArray(inArray, 0, inArray.Length, outArray, 0);
        return new MemoryStream(Encoding.UTF8.GetBytes(outArray));
    }
于 2013-10-02T11:38:42.960 に答える
12

バイトを Base64 にエンコードすることもできます。ストリームからこれを取得する方法はこちらを参照してください: How to convert an Stream into a byte[] in C#?

または、 .ToString() メソッドを使用してこれをエンコードすることも可能だと思います。

于 2013-10-02T09:51:08.723 に答える
5

ファイルが大きくなるため、これを行う方法についてはあまり選択肢がありません。使用する必要がある情報が破棄されるため、ファイルをその場で処理することはできません。私が見ることができる2つのオプションがあります:

  1. ファイル全体を読み込み、base64 エンコードし、エンコードされたデータを書き直します。
  2. ファイルを小さな断片に分けて読み取り、進行に合わせてエンコードします。同じディレクトリ内の一時ファイルにエンコードします。終了したら、元のファイルを削除し、一時ファイルの名前を変更します。

もちろん、ストリームの要点は、この種のシナリオを回避することです。コンテンツを作成してファイル ストリームに詰め込む代わりに、メモリ ストリームに詰め込みます。それをエンコードしてから、ディスクに保存します。

于 2013-10-02T09:46:46.593 に答える