Создание ZIP-архива из нескольких файлов на Silverlight

Пример сжатия одного или нескольких в ZIP-архив на Silverlight с помощью библиотеки SharpZipLib, и получение байтового массива этого архива для дальнейших манипуляций.

Для реализации сжатия создан класс ZipCompressor. Для сжатия используется библиотека SharpZipLib.

Класс, конечно, не отличается изяществом (главная его проблема — зависимость от последовательности вызовов методов), но вполне работоспособен и выполняет свои обязанности.

using System;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
 
 
namespace Samples.Silverlight.Compression
{
  /// <summary>
  /// <para>Класс позволяет сжать в ZIP-архив один или несколько файлов и 
  /// получить на выходе байтовый массив с компрессированными данными.</para>
  /// <para>Для сжатия используется библиотека SharpZipLib 
  /// (http://slsharpziplib.codeplex.com/).</para>
  /// </summary>
  public class ZipCompressor : IDisposable
  {
    private readonly MemoryStream _zippedMemoryStream;
    private readonly ZipOutputStream _zipOutputStream;
 
 
    public ZipCompressor()
    {
      _zippedMemoryStream = new MemoryStream();
      _zipOutputStream = new ZipOutputStream(_zippedMemoryStream);
      // Highest compression rating
      _zipOutputStream.SetLevel(9);
    }
 
 
    /// <summary>
    /// Метод позволяет добавить файл в архив.
    /// </summary>
    /// <param name="fileName">Имя добавляемого в архив файла.</param>
    /// <param name="fileContent">Текстовое содержимое добавляемого в архив
	/// файла.</param>
    /// <exception cref="Exception">Ошибка возникает при попытке добавить файл в
	/// закрытый архив, т.е. вызов метода AppendFile после вызова метода 
	/// GetCompressedByteArray.</exception>
    public void AppendFile(string fileName, string fileContent)
    {
      AppendFile(fileName, fileContent, Encoding.UTF8);
    }
 
 
    /// <summary>
    /// Метод позволяет добавить файл в архив.
    /// </summary>
    /// <param name="fileName">Имя добавляемого в архив файла.</param>
    /// <param name="fileContent">Текстовое содержимое добавляемого в архив 
	/// файла.</param>
    /// <param name="encoding">Кодировка, в которой необходимо сохранить 
	/// добавляемый файл.</param>
    /// <exception cref="Exception">Ошибка возникает при попытке добавить файл в
	/// закрытый архив, т.е. вызов метода AppendFile после вызова метода 
	/// GetCompressedByteArray.</exception>
    public void AppendFile(string fileName, string fileContent, Encoding encoding)
    {
      if (_zipOutputStream.IsFinished)
        throw new Exception("Попытка добавить файл в уже закрытый архив. "+
		  "Вызов метода AppendFile после вызова метода GetCompressedByteArray.");
 
      byte[] buffer;
      using (var file = new MemoryStream(encoding.GetBytes(fileContent)))
      {
        buffer = new byte[file.Length];
        file.Read(buffer, 0, buffer.Length);
      }
 
      var entry = new ZipEntry(fileName);
      _zipOutputStream.PutNextEntry(entry);
      _zipOutputStream.Write(buffer, 0, buffer.Length);
    }
 
 
    /// <summary>
    /// Метод закрывает архив для добавления новых файлов и возвращает 
	/// результирующий файл архива в виде массива байтов.
    /// </summary>
    public byte[] GetCompressedByteArray()
    {
      _zipOutputStream.Finish();
      return _zippedMemoryStream.ToArray();
    }
 
 
    public void Dispose()
    {
      _zipOutputStream.Dispose();
      _zippedMemoryStream.Dispose();
    }
  }
}

Использовать класс так:

var file1Content = "..."; // содержимое первого файла
var file2Content = "..."; // содержимое второго файла

// Сжатие происходит в памяти и сжимаются данные, также находящиеся в памяти. 
// Поэтому объявляем переменную, в которую сохраним результат сжатия.
byte[] compressedFileBytes;

// Производим компрессию двух файлов и получаем результат.
using (var compressor = new ZipCompressor())
{
   compressor.AppendFile("Test1.txt", file1Content);
   compressor.AppendFile("Test2.txt", file2Content, new CP1251());
   compressedFileBytes = compressor.GetCompressedByteArray();
}

// Сохраняем полученный архив на диск с помощью диалога SaveFileDialog.
using (var writer = dialog.OpenFile())
{
   writer.Write(compressedFileBytes, 0, compressedFileBytes.Length);
   writer.Close();
}

Первый файл сохраняется в архиве в Юникоде, а второй в кодировке Windows-1251 (класс CP1251 можно взять тут). Однако, если сохранять в архиве простые текстовые файлы, то все они будут в кодировке ANSI. Та или иная указанная кодировка будет использоваться только в случае специальных типов файлов, например, XML-файлов.

About the author

Добавить комментарий

Сказать спасибо

Способ платежа:

Подписаться на обновления

Укажите свой e-mail чтобы получать уведомления о новых статьях.

Присоединиться к еще 3 подписчикам