none
GZipStream сжатие нескольких потоков в один архив RRS feed

  • Вопрос

  • Добрый вечер. Подскажите пожалуйста, как можно несколько gzip потоков из одного файла соединить и записать в другой файл(поток)?

    Делаю примерно так, создаю очередь из объектов, которые содержать gzipstream'ы и буферы со сжатыми данными.

    Если я пытаюсь пройтись по очереди и попытаться зписать(someStream.Write();) из каждого буфера данные, то записываются только из одного, другие не могут ничего записать в файл из-за ошибки, что файл занят. Даже если после записи я вызываю stream.Close();

    Как быть?

    Опасаюсь конкатенировать буфферы из-за возможности того, что не хватит оперативной памяти на общий буффер.

    PS

    Необходимо выполнить эту задачу стандартными средствами, без использования сторонних библиотек.



    • Изменено akavoid 14 августа 2013 г. 10:47
    14 августа 2013 г. 10:46

Ответы

  • Я решил по другому.

    Реализовал очередь поставщик-потребитель. 

    А про этот вопрос тоже уже забыл.

    • Помечено в качестве ответа akavoid 29 августа 2013 г. 2:23
    29 августа 2013 г. 2:23

Все ответы

  • Здравствуйте. Покажите код, чтобы было нагляднее.

    Сделаем содержимое сообщества лучше, вместе!

    14 августа 2013 г. 17:32
    Модератор
  • class Program
        {
            static void Main(string[] args)
            {
                string inputFile = "Test.txt";
                string outFile = "Test.gz";
                int bufferLength = 8192;
                FileInfo info = new FileInfo(inputFile);
                long stateCount = info.Length/bufferLength;
                Queue<State> states = new Queue<State>();
    
                var fileStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read);
                var outStream = new FileStream(outFile, FileMode.Create, FileAccess.Write);
    
                for (int i = 0; i < stateCount; i++)
                {
                    states.Enqueue(new State(new ManualResetEvent(false),
                                             new GZipStream(outStream, CompressionMode.Compress), 
                                             fileStream, bufferLength));
                }
    
                foreach (var state in states)
                {
                    state.RunTask();
                }
    
            }
                    
            
        }
    
        class State
        {
            public byte[] _buffer;
            public int _wasRead;
            public ManualResetEvent ResetEvent { get; private set; }
            public GZipStream GZip { get; private set; }
            public FileStream File { get; set; }
    
    
            public void RunTask()
            {
                if(Read())
                {
                        Console.WriteLine("Прочитано");
                    if(Write())
                    {
                        Console.WriteLine("Записано");
                    }
                }
            }
            private bool Read()
            {
                try
                {
                    Console.WriteLine("Начало операции чтения");
                    do
                    {
                        if (File.CanRead)
                        {
                            _wasRead = File.Read(_buffer, 0, _buffer.Length);
                        }
                    } while (_wasRead==0);
                    Console.WriteLine("Чтение завершилось успешно");
                    ResetEvent.Set();
                    return true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Ошибка: {0}", ex.Message);
                    return false;
                }
            }
    
            private bool Write()
            {
                try
                {
                    Console.WriteLine("Начало операции записи");
                    bool written = false;
                    do
                    {
                        if (GZip.CanWrite)
                        {
                            GZip.Write(_buffer, 0, _wasRead);
                            GZip.Close();
                            written = true;
                        }
                    } while (!written);
                    Console.WriteLine("Запись завершилась успешно");
    
                    return true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Ошибка: {0}", ex.Message);
                    return false;
                }
                
            }
    
            public State(ManualResetEvent resetEvent, GZipStream gzip, FileStream file, int bufferLength)
            {
                _wasRead = 0;
                _buffer = new byte[bufferLength];
                ResetEvent = resetEvent;
                GZip = gzip;
                File = file;
            }
        }

    Ну вот небольшие наброски. Не обращайте внимания на manualResetEvent, я пока его не использую.

    Смысл кода:

             Узнать размер файла
             определить число элементов в очереди
             Создать кол-во элементов и записать их в очередь
             Для каждого из элементов выполнить чтение и запись.

    Но после первой успешной записи файл блокируется и все. И дальше я брожу по вечному циклу в методе write

    15 августа 2013 г. 2:48
  • Иногда про некоторые вопросы совсем забываю, а иногда просто нет времени. Про ваш просто забыл.

    Ошибка у вас от того, что на второй итерации в цикле foreach ваш код заходит в бесконечный цикл, и приложение зависает.

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


    Сделаем содержимое сообщества лучше, вместе!

    21 августа 2013 г. 13:56
    Модератор
  • Я решил по другому.

    Реализовал очередь поставщик-потребитель. 

    А про этот вопрос тоже уже забыл.

    • Помечено в качестве ответа akavoid 29 августа 2013 г. 2:23
    29 августа 2013 г. 2:23