Сжатие файлов в .net 2.0

  • Автор темы NikSoft
  • Дата начала
Статус
Закрыто для дальнейших ответов.
N

NikSoft

#1
Платформа .NET 2.0 имеет новое пространство имен System.IO.Compression, позволяющее сжимать и восстанавливать потоки(streams) несколькими предложениями. Мы рассмотрим GzipStream класс из этого пространства имен.
Этот класс сжимает данные в соответствии с форматом gzip(RFC 1952 http://go.microsoft.com/fwlink/?linkid=45286). Размер исходного файла не может превышать 4 Gb.
GzipStream класс не может добавлять(извлекать) файлы в(из) “.zip” архивы. Когда вы создаете класс, наследуемый GzipStream, необходимо переопределить(overrides) следующие члены класса: CanSeek, CanWrite, CanRead.
Рассмотрим пример. Сначала мы считываем в буфер файл, который необходимо сжать. Затем определяем ms обьект типа MemoryStream, который будет содержать сжатые данные. Собственно сжатие осуществляет метод Write класса GzipStream. Диалоговое окно выводит размер файла до и после сжатия.
Восстановление данных начинается с установки позиции ms обьекта к нулю. Создаем новый обьект типа GzipStream с ключом CompressMode.Decompress. Собственно восстановление данных осуществляется методом ReadAllBytesFromStream, которые сохраняются в буфере decompresBuffer.
Наконец диалоговое окно выводит размер восстановленных данных.
Код:
private void button2_Click(object sender, EventArgs e)
{
string	 filename = @"C:\Disk to burn\Books\Compression\GZipStream.doc";
FileStream infile;
try
{
infile = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
byte[] buffer = new byte[infile.Length];
int count = infile.Read(buffer, 0, buffer.Length);
infile.Close();

MemoryStream ms = new MemoryStream();
// memory stream будет содержать сжатые данные
GZipStream comprZipStream = new GZipStream(ms , CompressionMode.Compress, true);
comprZipStream.Write(buffer, 0, buffer.Length);
comprZipStream.Close();
MessageBox.Show(string.Format("Исходный размер: {0}, Размер после сжатия: {1}",	  buffer.Length, ms.Length));

// Установи позицию memory stream, с которой начинать восстановление данных
ms.Position = 0;
GZipStream zipStream = new GZipStream(ms, CompressionMode.Decompress);
byte[] decompresBuffer = new byte[buffer.Length + 100];
// Чтение потока
int totalCount = ReadAllBytesFromStream(zipStream, decompresBuffer);
MessageBox.Show(string.Format("Восстановленный размер: {0} bytes", totalCount));
if( !CompareData(buffer, buffer.Length, decompresBuffer, totalCount) ) 
{
MessageBox.Show("Ошибка. Два буфера различны");
}
zipStream.Close(); 
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message + ex.StackTrace);
}
}

public static int ReadAllBytesFromStream(Stream stream, byte[] buffer) 
{
int offset = 0,totalCount = 0; 
while (true) 
{
int bytesRead = stream.Read(buffer, offset, 100); 
if ( bytesRead == 0)
{
break;
} 
offset += bytesRead;
totalCount += bytesRead; 
}
return totalCount;
} 

public static bool CompareData(byte[] buf1, int len1, byte[] buf2, int len2) 
{
if (len1 != len2) 
{ 
return false;
}
for ( int i= 0; i< len1; i++) 
{
if ( buf1[i] != buf2[i]) 
{
return false;
}
}
return true; 
}
 
Статус
Закрыто для дальнейших ответов.