Я создал метод для возврата всех несжатых байтов из сжатого файла.
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 МБ для всех небольших. Поэтому у меня есть несколько вопросов:
Read
один раз)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();
}
}
Прежде всего, есть ли такой способ в этой структуре? Или лучший способ сделать это?
Используйте MemoryStream
в качестве буфера и используйте Stream.Copy
для копирования данных в одну строку.
Есть ли способ получить несжатый размер сжатого файла?
Нет, deflate - это потоковый формат. Вы можете угадать некоторое значение, потому что несжатые данные, вероятно, будут больше, чем сжатый вход. Наверное, пустая трата времени на это.
Я использовал List, поэтому мне не нужно вручную перераспределять массив байтов. Есть ли более эффективный способ добавления байтов?
Это ужасно неэффективно. Класс List
будет перечислять массив байтов, в который вы проходите, и добавлять байты один за другим. Ожоги CPU как сумасшедшие в большом файле. Используйте MemoryStream
. Он использует memcpy
для выполнения своих операций копирования.
Кроме того, у вас есть ошибка: вы не используете возвращаемое значение из Read для определения количества прочитанных байтов. Вы всегда добавляете один полный буфер. Это уходит с предложенным алгоритмом.