Как ежесекундно проверять данные в потоке Stream (FileStream, StreamReader, CryptoStream)?

Программа-шифратор. Вот пример кода шифрования
public static void EncryptFile(string inputFile, string outputFile, byte[] Key)
        {
            using (var rijndael = RijndaelManaged.Create())
            {
                rijndael.IV = IV;
                rijndael.Key = Key;
                using (var inputStream = File.OpenRead(inputFile))
                using (var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
                using (var encStream = new CryptoStream(outputStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    inputStream.CopyTo(encStream);
                }
            }
        }

Мне нужно, чтобы по мере шифрования заполнялся ProgressBar. Как я понял:
1) файл до шифрования и после имеет одинаковую длину (inputStream.Lengh)
2) когда создаётся выходной поток outputStream его изначальная длина outputStream.Lengh равна 0. То есть по идее, по мере шифрования у выходного потока увеличивается длина.

Как мне кажется оптимальным решением будет сделать так:
1) Максимальное значение прогресс бара, 100% - это изначальная длина файла
2) Каждую милисекунду считывать длину файла outputStream и соответственно обновлять значение прогресс бара.

Проблема: не могу разобраться со считыванием. Как передать в таймер событие tick два потока inputStream и outputStream, чтобы можно было каждую милисекунду считывать данные?
Возможно есть более правильное решение???
Пожалуйста, если не трудно, опишите подробнее, потому что я новичок и не шарю за все фишки :))
  • Вопрос задан
  • 123 просмотра
Решения вопроса 1
twobomb
@twobomb
Пример для консольки, если у тебя winform или wpf то вместо той херни которая в цикле while вызывай инвок и меняй состояния бара, ток слип оставь можешь сделать меньше
public static void EncryptFile(string inputFile, string outputFile){
            using (var rijndael = RijndaelManaged.Create()){
                rijndael.GenerateIV();
                rijndael.GenerateKey();
                using (var inputStream = File.OpenRead(inputFile))
                using (var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
                using (var encStream = new CryptoStream(outputStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write)){
                    Task.Run(() =>{
                        double len = inputStream.Length;
                        while (outputStream.Length < inputStream.Length){
                            int currentLineCursor = Console.CursorTop;
                            Console.SetCursorPosition(0, Console.CursorTop);
                            Console.Write(new string(' ', Console.WindowWidth));
                            Console.SetCursorPosition(0, currentLineCursor);
                            Console.Write(String.Format("Завершено на {0}%", Math.Round(((double)outputStream.Length / len * 100), 2)));
                            Thread.Sleep(100);
                        }

                    });
                    inputStream.CopyTo(encStream);
                    Console.WriteLine("\nЗавершено!");
                }
            }
        }

P.S. Кстате всё что в таске можешь обернуть в try и ловить System.ObjectDisposedException, если уловил значит оно уже дошифровало и сделало диспос, хотя если не уловишь оно и так завершиться, так вот можно даже white(true) использовать, то условие бесполезно
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@none7
Оберни inputStream или outputStream в класс реализующий Stream. Таким образом класс CryptoStream сам уведомит Ваш код о любых изменениях. Эти изменения тут же писать в прогрессбар, если конечно изменение значительно отличается от данных которые уже отображены.
Ответ написан
freeExec
@freeExec
Участник OpenStreetMap
Положить в массив и передать его.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы