File.ReadAllBytes需要大量的RAM,有更好的方法吗?

时间:2018-02-04 20:11:01

标签: c#

我正忙着使用加密库,我想加密大文件(使用AES GCM)。目前,在Chipher编写临时文件CryptoStream后,我有这个用于加密文件:

byte[] Chiper = File.ReadAllBytes(BUFFER_PATH);

                    // Retrieve tag and create array to hold encrypted data.
                    byte[] AuthTag = encryptor.GetTag();
                    byte[] encrypted = new byte[Chiper.Length + aes.IV.Length + AuthTag.Length];

                    // Set needed data in byte array.
                    aes.IV.CopyTo(encrypted, 0);
                    AuthTag.CopyTo(encrypted, IV_LENGTH);
                    Chiper.CopyTo(encrypted, IV_LENGTH + TAG_LENGTH);
                    File.WriteAllBytes(END_PATH, encrypted);

此功能正常,但根据文件大小需要大量内存。这有更好的方法吗?我尝试使用FileStream虽然它开始与我的代码冲突。有没有办法使用更少或没有内存来保存Chiper(byte[])

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试编写一个包含三条信息的复合文件 - 标记,IV和密文。鉴于在加密完成之前您无法获取标记值,您将尝试在加密完成后合并数据。

当您尝试将大型加密文件加载到内存中时,会出现此问题。幸运的是,流为此提供了一个很好的简单解决方案:

byte[] authTag = encryptor.GetTag();

using (var tempfile = File.OpenRead(BUFER_PATH))
using (var outstream = File.Create(END_PATH))
{
    // write tag
    outstream.Write(authTag, 0, authTag.Length);
    // write IV
    outstream.Write(aes.IV, 0, aes.IV.Length);
    // copy data from source file to output file
    tempfile.CopyTo(outstream);
}

另一方面,如果您提前知道标签和IV的大小,您也可以将数据直接写入输出文件。只需在文件开头为标记值分配空间,然后返回并在事后写入。这样可以节省您使用临时文件的费用。