С# повторно использует GZipStream для более чем одной распаковки

Мне нужно сжимать и распаковывать миллионы строк по отдельности. Первый цикл работает. Второй нет. В основном я не знаю, как использовать потоки. Как мне заставить работать второй метод, который повторно использует потоки?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            string s = "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah ";
            for (int i=0; i<10000; ++i) {
                var aCompressed = Zip(Encoding.ASCII.GetBytes(s));
                var aDecompressed = UnZip(aCompressed, 0, aCompressed.Length);
                string sDbg = System.Text.Encoding.ASCII.GetString(aDecompressed);
                Debug.Assert(sDbg == s);
            }
            // This loop is an utter failure.
            var UnZipper = new CUnZip(); // attempt to setup all the unzip framework once
            for (int i = 0; i < 10000; ++i) {
                var aCompressed = Zip(Encoding.ASCII.GetBytes(s));
                var aDecompressed = UnZipper.UnZip(aCompressed, 0, aCompressed.Length);
                string sDbg = System.Text.Encoding.ASCII.GetString(aDecompressed);
                Debug.Assert(sDbg == s);
            }
        }
        static byte[] Zip(byte[] aIn) {
            using (var outStream = new MemoryStream()) {
                using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress))
                using (var mStream = new MemoryStream(aIn))
                    mStream.CopyTo(tinyStream);
                return outStream.ToArray();
            }
        }
        static byte[] UnZip(byte[] aIn, int i0, int cb) {
            using (var inStream = new MemoryStream(aIn, i0, cb))
            using (var bigStream = new GZipStream(inStream, CompressionMode.Decompress))
            using (var bigStreamOut = new MemoryStream()) {
                bigStream.CopyTo(bigStreamOut);
                return bigStreamOut.ToArray();
            }
        }
        // this class is an utter failure
        class CUnZip {
            GZipStream bigStream;
            MemoryStream inStream, bigStreamOut;
            BinaryWriter argh;
            public CUnZip() {
                inStream = new MemoryStream();
                argh = new BinaryWriter(inStream);
                bigStream = new GZipStream(inStream, CompressionMode.Decompress);
                bigStreamOut = new MemoryStream();
            }
            public byte[] UnZip(byte[] aIn, int i0, int cb) {
                argh.Write(aIn, i0, cb);
                argh.Flush();
                bigStream.CopyTo(bigStreamOut);
                return bigStreamOut.ToArray();
            }
        }
    }
}

person johnnycrash    schedule 24.09.2016    source источник
comment
Определить не работает. Неправильные результаты? Ошибки? Что-то другое? Но проще говоря: вы не можете просто засунуть больше данных в декомпрессию и предположить, что она с радостью подчинится и сделает то, что вы хотите. Вы должны создать новые со свежим состоянием.   -  person Sami Kuhmonen    schedule 24.09.2016
comment
Пожалуйста, укажите конкретные детали, вместо того, чтобы предполагать, что мы сможем угадать, первый и второй циклы и точки сбоев, как вы их воспринимаете.   -  person Mrinal Kamboj    schedule 24.09.2016
comment
bigStream = new GZipStream(inStream, ... Почему вы используете inStream там. Ради забавы?   -  person Orkhan Alikhanov    schedule 24.09.2016
comment
@Орхан. Это первый раз, когда я использовал потоки. Я сделал это, потому что я не знаю лучше.   -  person johnnycrash    schedule 24.09.2016
comment
@Мринал. Второй цикл всегда производит пустую строку.   -  person johnnycrash    schedule 24.09.2016
comment
@Сами. Второй цикл всегда производит пустую строку   -  person johnnycrash    schedule 24.09.2016
comment
@Орхан. Как ты это делаешь без инстрима?   -  person johnnycrash    schedule 24.09.2016
comment
@johnnycrash: Хм, я пропустил, что ты пишешь в instream, используя BinaryWriter   -  person Orkhan Alikhanov    schedule 24.09.2016
comment
@orkhan есть идеи, как сделать это по-другому? Могу ли я использовать BinaryWriter для записи в GZipStream?   -  person johnnycrash    schedule 24.09.2016


Ответы (1)


Протестированный ваш код решит проблему:

inStream.Position = 0;

Установите его после argh.Flush() в class CUnZip - UnZip Method

Подробности:

Поскольку вы повторно используете MemoryStream в классе CUnZip, его позиция устанавливается на последний записанный байт, и для выполнения любой операции, которая требует его чтения, вам нужно сбросить position в начало (0), иначе он ничего не имеет читать, поэтому даже когда stream содержит данные, их нельзя прочитать, так как они указывали на конец stream

person Mrinal Kamboj    schedule 24.09.2016
comment
Поток gzip может иметь некоторое внутреннее состояние, которое нельзя сбросить. - person usr; 24.09.2016
comment
Повторное использование всего сделало разархивирование НАМНОГО быстрее. - person johnnycrash; 24.09.2016