web-dev-qa-db-ja.com

Base64エンコードa PDF C#で?

誰かがこれを行う方法についていくつかの光を提供できますか?私は通常のテキストまたはバイト配列に対してこれを行うことができますが、PDFへのアプローチ方法がわかりません。最初にPDFをバイト配列に入れますか?

30
Tone

_File.ReadAllBytes_ を使用してPDFファイルをロードし、次に Convert.ToBase64String(bytes) を使用してバイト配列を通常どおりにエンコードします=。

45
Andrew Rollings

一度に大量のメモリを書き込む必要がないように、これをチャンクで行う方法があります。

.Netには、チャンクを実行できるエンコーダーが含まれていますが、それはちょっと変わった場所にあります。彼らはそれをSystem.Security.Cryptography名前空間に入れました。

以下のサンプルコードをテストしましたが、私の方法または上記のAndrewの方法を使用して同じ出力が得られます。

仕組みは次のとおりです。CryptoStreamというクラスを起動します。これは、別のストリームにプラグインする一種のアダプターです。 CryptoTransformと呼ばれるクラスをCryptoStream(ファイル/メモリ/ネットワークストリームにアタッチされている)にプラグインし、ストリームからの読み取りまたはストリームへの書き込み中にデータに対してデータ変換を実行します。

通常、変換は暗号化/復号化ですが、.netにはToBase64変換とFromBase64変換も含まれているため、暗号化は行わず、エンコードのみを行います。

これがコードです。出力を比較できるように、Andrewの提案の(多分、名前が不十分な)実装を含めました。


    class Base64Encoder
    {
        public void Encode(string inFileName, string outFileName)
        {
            System.Security.Cryptography.ICryptoTransform transform = new System.Security.Cryptography.ToBase64Transform();
            using(System.IO.FileStream inFile = System.IO.File.OpenRead(inFileName),
                                      outFile = System.IO.File.Create(outFileName))
            using (System.Security.Cryptography.CryptoStream cryptStream = new System.Security.Cryptography.CryptoStream(outFile, transform, System.Security.Cryptography.CryptoStreamMode.Write))
            {
                // I'm going to use a 4k buffer, tune this as needed
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = inFile.Read(buffer, 0, buffer.Length)) > 0)
                    cryptStream.Write(buffer, 0, bytesRead);

                cryptStream.FlushFinalBlock();
            }
        }

        public void Decode(string inFileName, string outFileName)
        {
            System.Security.Cryptography.ICryptoTransform transform = new System.Security.Cryptography.FromBase64Transform();
            using (System.IO.FileStream inFile = System.IO.File.OpenRead(inFileName),
                                      outFile = System.IO.File.Create(outFileName))
            using (System.Security.Cryptography.CryptoStream cryptStream = new System.Security.Cryptography.CryptoStream(inFile, transform, System.Security.Cryptography.CryptoStreamMode.Read))
            {
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = cryptStream.Read(buffer, 0, buffer.Length)) > 0)
                    outFile.Write(buffer, 0, bytesRead);

                outFile.Flush();
            }
        }

        // this version of Encode pulls everything into memory at once
        // you can compare the output of my Encode method above to the output of this one
        // the output should be identical, but the crytostream version
        // will use way less memory on a large file than this version.
        public void MemoryEncode(string inFileName, string outFileName)
        {
            byte[] bytes = System.IO.File.ReadAllBytes(inFileName);
            System.IO.File.WriteAllText(outFileName, System.Convert.ToBase64String(bytes));
        }
    }

私はまた、CryptoStreamを接続する場所をいじっています。 Encodeメソッドでは、出力(書き込み)ストリームにアタッチしているので、CryptoStreamをインスタンス化するときは、そのWrite()メソッドを使用します。

読み取るときは、入力(読み取り)ストリームにアタッチするので、CryptoStreamでreadメソッドを使用します。どのストリームに接続するかは特に問題ではありません。適切なReadまたはWrite列挙型メンバーをCryptoStreamのコンストラクターに渡すだけです。

35
JMarsch