web-dev-qa-db-ja.com

C#でFileStreamをbase64にエンコードする

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

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

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

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

28
feedwall

バイトをBase64にエンコードすることもできます。ストリームからこれを取得する方法は、こちらを参照してください: C#でストリームをbyte []に​​変換する方法

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

11
alpham8

拡張方法として簡単なもの

public static class Extensions
{
    public static Stream ConvertToBase64(this Stream stream)
    {
        byte[] bytes;
        using (var memoryStream = new MemoryStream())
        {
            stream.CopyTo(memoryStream);
            bytes = memoryStream.ToArray();
        }

        string base64 = Convert.ToBase64String(bytes);
        return new MemoryStream(Encoding.UTF8.GetBytes(base64));
    }
}
17
chris31389

何か試してみてくださいlike that:

    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));
    }
15
Jacob

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

  1. ファイル全体を読み込み、base64エンコードし、エンコードされたデータを書き換えます。
  2. ファイルを少しずつ読んで、進めながらエンコードします。同じディレクトリ内の一時ファイルにエンコードします。終了したら、元のファイルを削除し、一時ファイルの名前を変更します。

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

5
David Heffernan

サイズが4GBを超えるファイルのような大きなストリームを扱う場合、ファイルをメモリに(Byte[]として)ロードしたくないのは、それが非常に遅いだけでなく、 64ビットプロセスは、Byte[]が2GB(またはgcAllowVeryLargeObjectsで4GB)を超えることはできません。

幸いなことに、.NETには、ストリームをチャンクで処理するToBase64Transformと呼ばれるきちんとしたヘルパーがあります。そのようです:

using System.Security.Cryptography;

public static Stream EncodeStreamUsingBase64( Stream input )
{
    if( input == null ) throw new ArgumentNullException( nameof(input) );

    ICryptoTransform xf = new ToBase64Transform();

    return new CryptoStream( input, xf, CryptoStreamMode.Write, leaveOpen: false );
}

したがって、次のように使用できます。

using( FileStream inputFile = new FileStream( @"C:\VeryLargeFile.bin", FileMode.Open, FileAccess.Read ) )
using( Stream base64Stream = EncodeStreamUsingBase64( fs ) )
using( FileStream outputFile = new FileStream( @"C:\VeryLargeBase64File.txt", FileMode.CreateNew, FileAccess.Write ) )
{
    await base64Stream.CopyToAsync( outputFile );
}
0
Dai