Получить все несжатые байты из сжатого файла

1

Я создал метод для возврата всех несжатых байтов из сжатого файла.

    public static byte[] GetAllBytesFromCompressedFile(string fullPath)
    {
        const int blockSize = 10000;
        byte[] block = new byte[blockSize];
        List<byte> allBytes = new List<byte>(blockSize);

        int counter = 0;
        using (FileStream file = new FileStream(fullPath, FileMode.Open))
        {
            using (DeflateStream compress = new DeflateStream(file, CompressionMode.Decompress))
            {
                int bytesRead = 0;
                do
                {
                    bytesRead = compress.Read(block, 0, blockSize);
                    counter += bytesRead;
                    allBytes.AddRange(block);
                } while (bytesRead == blockSize);
            }
        }

        return allBytes.GetRange(0, counter).ToArray();
    }

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

  1. Прежде всего, есть ли такой способ в этой структуре? Или лучший способ сделать это?
  2. Есть ли способ получить несжатый размер сжатого файла? (тогда мне не нужно было бы получать блоки в цикле и могли бы вызвать Read один раз)
  3. Я использовал List<byte> поэтому мне не нужно вручную перераспределять массив байтов. Есть ли более эффективный способ добавления байтов?

Я поставлю свой новый код здесь, хотя это, вероятно, не является трудной проблемой для большинства людей. Но, возможно, кто-то видит что-то еще, что можно улучшить, например, явно задавая размер буфера (?)

    public static byte[] GetAllBytesFromCompressedFile(string fullPath)
    {
        using (MemoryStream allBytes = new MemoryStream())
        {
            using (FileStream file = new FileStream(fullPath, FileMode.Open))
            {
                using (DeflateStream compress = new DeflateStream(file, CompressionMode.Decompress))
                {
                    compress.CopyTo(allBytes);
                }
            }

            return allBytes.ToArray();
        }
    }
Теги:
deflatestream

1 ответ

4
Лучший ответ

Прежде всего, есть ли такой способ в этой структуре? Или лучший способ сделать это?

Используйте MemoryStream в качестве буфера и используйте Stream.Copy для копирования данных в одну строку.

Есть ли способ получить несжатый размер сжатого файла?

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

Я использовал List, поэтому мне не нужно вручную перераспределять массив байтов. Есть ли более эффективный способ добавления байтов?

Это ужасно неэффективно. Класс List будет перечислять массив байтов, в который вы проходите, и добавлять байты один за другим. Ожоги CPU как сумасшедшие в большом файле. Используйте MemoryStream. Он использует memcpy для выполнения своих операций копирования.

Кроме того, у вас есть ошибка: вы не используете возвращаемое значение из Read для определения количества прочитанных байтов. Вы всегда добавляете один полный буфер. Это уходит с предложенным алгоритмом.

  • 1
    Спасибо за ответ и, в частности, подробности использования Списка. И за указание на ошибку :-)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню