Кодировать FileStream до base64 с помощью С#

Я знаю, как кодировать/декодировать простую строку в/из base64.

Но как бы это сделать, если данные уже были записаны в объект FileStream. Скажем, у меня есть только доступ к объекту FileStream, а не к ранее сохраненным исходным данным. Как мне закодировать FileStream на base64, прежде чем я очищу FileStream до файла.

Ofc Я мог бы просто открыть свой файл и закодировать/декодировать его после того, как я написал FileStream в файл, но я хотел бы сделать это всего за один шаг, не делая двух файловых операций один за другим. Файл может быть больше, и для загрузки, зашифрования и сохранения его снова потребуется два раза, после того, как он был сохранен за короткое время раньше.

Возможно, кто-то из вас знает лучшее решение? Могу ли я преобразовать FileStream в строку, закодировать строку и затем преобразовать строку обратно в FileStream, например, или что бы я сделал и как выглядел бы такой код?

Ответ 1

Вы также можете кодировать байты в Base64. Как получить это из потока, см. Здесь: Как преобразовать поток в байт [] в С#?

Или я думаю, что также следует использовать метод .ToString() и кодировать это.

Ответ 2

Легкий как метод расширения

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

Ответ 3

Вы можете попробовать что-то как, которое:

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

Ответ 4

Поскольку файл будет больше, у вас нет большого выбора в том, как это сделать. Вы не можете обработать файл на месте, так как это уничтожит информацию, которую вам нужно использовать. У меня есть два варианта:

  • Прочитайте весь файл, base64 закодируйте, перепишите закодированные данные.
  • Прочитайте файл в меньших частях, кодируя по мере продвижения. Кодировать во временный файл в том же каталоге. Когда вы закончите, удалите исходный файл и переименуйте временный файл.

Конечно, весь смысл потоков - избежать такого сценария. Вместо того, чтобы создавать контент и набивать его в поток файлов, залейте его в поток памяти. Затем закодируйте это и только затем сохраните на диск.

Ответ 5

При работе с большими потоками, такими как файл размером более 4 ГБ, вы не хотите загружать файл в память (как Byte[]), потому что он не только очень медленный, но также может вызвать сбой, как даже в 64- битовые процессы Byte[] не могут превышать 2 ГБ (или 4 ГБ с gcAllowVeryLargeObjects).

К счастью, в .NET есть полезный помощник под названием ToBase64Transform, который обрабатывает поток кусками.

Вы используете его с CryptoStream примерно так:

using( FileStream   inputFile    = new FileStream( @"C:\VeryLargeFile.bin", FileMode.Open, FileAccess.Read ) )
using( CryptoStream base64Stream = new CryptoStream( inputFile, new ToBase64Transform(), CryptoStreamMode.Read ) )
using( FileStream   outputFile   = new FileStream( @"C:\VeryLargeBase64File.txt", FileMode.CreateNew, FileAccess.Write ) )
{
    await base64Stream.CopyToAsync( outputFile ).ConfigureAwait(false);
}