June 26, 2020

Архивация данных на языке C#

Пример архивации данных для новичков

В этом примере вы сможете с лёгкостью архивировать ваши данные файлов на версии .NetFramework от v4.0 - v4.5 и выше.

Нажмите: скачать всё необходимое для вашей работы! (В этом архиве лежат все нужные классы которые вы можете использовать для работы с архивацией)


Начнём работу со стандартными архиваторами которые установлены на машине пользователя, а это 7-Zip , WinRAR

Для работы мне потребовалась некоторая документация:

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

[Внимание] В данном коде используется версия C# 8.0

Класс для нахождения стандартных архиваторов на компьютере через реестр.

Класс для нахождения архиваторов через Реестр Windows
namespace Archiver
{
    using Microsoft.Win32;
    public static class RegZipPath 
    {
        /// <summary>
        /// Метод для поиска установленного WinRAR архиватора в системе через реестр
        /// </summary>
        /// <returns>Путь к <b>.exe</b> архиватору</returns>
        public static string FindWinRar()
        {
            string result = string.Empty;
            try
            {
                const string REGPATH = @"WinRAR\Shell\Open\Command";
                using RegistryKey Root = Registry.ClassesRoot.OpenSubKey(REGPATH);
                string winrarPath = (Root?.GetValue(""))?.ToString();
                winrarPath = winrarPath.Substring(1, winrarPath.Length - 7);
                result = winrarPath;
            }
            catch { }
            return result;
        }
        /// <summary>
        /// Метод для поиска установленного 7-Zip архиватора в системе через реестр
        /// </summary>
        /// <returns>Путь к <b>.exe</b> архиватору</returns>
        public static string FindWinZip()
        {
            string result = string.Empty;
            try
            {
                const string REGPATH = @"Software\7-Zip";
                using RegistryKey zip = Registry.CurrentUser.OpenSubKey(REGPATH);
                result = string.Concat((zip?.GetValue("Path"))?.ToString(), "7z.exe");
            }
            catch { }
            return result;
        }
    }
}

Эти два метода из класса RegZipPath.cs позволять находить путь к .exe-шнику нужного архиватора, если тот установлен в системе.


Теперь перейдём в другой класс который будет отвечать за саму архивацию папки.

Класс в котором используются 2-а метода для архивации папки с максимальным сжатием и разархивации архива.

Класс для архивации данных через стандартные архиваторы Windows ( Winrar, Zip )

Для 7-Zip используется данный метод PackZip


Расшифровка аргументов для Архивации папки:

  • a ( Добавление файлов в архив )
t - тип. Определяет тип архива, который вы хотите создать:
-t7z Формат: 7Z
-tgzip Формат: GZIP
-tzip Формат: ZIP
-tbzip2 Формат: BZIP2
-ttar Формат: TAR
-tiso Формат: ISO
-tudf Формат: UDF
  • -r ( Обрабатывать вложенные папки )
  • {outputzip}.zip ( Имя выходного архива )
  • {datapath} (Путь к папке, которую нужно архивировать)
  • -mx=9 ( Уровень сжатия архива, 1 - Fast | 9 Ultra )

public static class ArchCmd
{
   /// <summary>
   /// Метод для архивации папки с ультра сжатием.
   /// </summary>
   /// <param name="zipshell">Путь к архиватору</param>
   /// <param name="datapath">Путь к папке которую нужно архивировать</param>
   /// <param name="outputzip">Выходной путь, куда сохранять с новым именем архива</param>
   public static void PackZip(string zipshell, string datapath, string outputzip)
   {
     if (File.Exists(zipshell) && (!string.IsNullOrWhiteSpace(datapath) || !string.IsNullOrWhiteSpace(outputzip)))
     {
        var pro = new ProcessStartInfo
        {
           WindowStyle = ProcessWindowStyle.Hidden,
           FileName = zipshell,
           Arguments = $@"a -tzip -r {outputzip}.zip {datapath} -mx=9"
        };
        using var x = Process.Start(pro);
        x.Refresh();
        x.WaitForExit(); // Обязательно)
      }
   }

Так же используется метод для распаковки UnpackZip

Расшифровка аргументов для распаковки архива:

  • x (Принимающий архив который нужно распаковать)
  • -o (Выходная директория распакованного архива)
/// <summary>
/// Метод для распаковки .zip архива
/// </summary>
/// <param name="zipshell">Путь к архиватору</param>
/// <param name="inputzip">Путь к папке которую нужно разархивировать</param>
/// <param name="outputdir">Выходной путь, куда сохранять папку</param>
public static void UnpackZip(string zipshell, string inputzip, string outputdir)
{
  if (File.Exists(zipshell) && (!string.IsNullOrWhiteSpace(inputzip) || !string.IsNullOrWhiteSpace(outputdir)))
  {
     var pro = new ProcessStartInfo
     {
        WindowStyle = ProcessWindowStyle.Hidden,
        FileName = zipshell,
        Arguments = quot;x {inputzip}.zip -o{outputdir}"
     };
     using var x = Process.Start(pro);
     x.WaitForExit();
   }
}

Пример использования для Zip

/* -Примеры использования-
private static readonly string CurrDir = Environment.CurrentDirectory; // Текущая директория
private static readonly string Desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); // Рабочий стол
ZipDot - Имя папки которую архивируем. 
r3xq1 - Имя архива ( без .zip )
Для архивации: PackZip(RegZipPath.FindWinZip(), Path.Combine(CurrDir, "ZipDot"), Path.Combine(Desktop, "r3xq1"));
Для распаковки: UnpackZip(RegZipPath.FindWinZip(), Path.Combine(Desktop, "r3xq1"), Path.Combine(Desktop, "r3xq1"));
*/

Отлично! С методом Zip архивации и разархивации мы разобрались)


Теперь сделаем тоже самое только для работы с WinRAR архиватором.

Расшифровка аргументов:

  • a (Добавление файлов в архив)
  • -ep1 (Исключить из пути базовую папку)
  • -m5 (Установить метод сжатия, 1 - Fast | 5 - Ultra)
  • -r (Обрабатывать вложенные папки )
  • -y (Подразумевать ответ "Да" на все запросы - На всякий случай, чтобы не было лишних консольных окошек)
  • {outputzip}.zip (Имя выходного архива)
  • {datapath} (Путь к папке, которую нужно архивировать)

/// <summary>
/// Метод для архивации папки с ультра сжатием.
/// </summary>
/// <param name="rarshell">Путь к архиватору</param>
/// <param name="datapath">Путь к папке которую нужно архивировать</param>
/// <param name="outputzip">Выходной путь, куда сохранять с новым именем архива</param>
public static void PackRar(string rarshell, string datapath, string outputzip)
{
  if (File.Exists(rarshell) && (!string.IsNullOrWhiteSpace(datapath) || !string.IsNullOrWhiteSpace(outputzip)))
  {
     var pro = new ProcessStartInfo
     {
        WindowStyle = ProcessWindowStyle.Hidden,
        FileName = rarshell,
        Arguments = $@"a -ep1 -m5 -r -y {outputzip}.rar {datapath}"
     };
     using var x = Process.Start(pro);
     x.Refresh();
     x.WaitForExit();
   }
}

Вызов точно так же как с Zip только за место первого аргумента даём путь нахождения Winrar архиватора а не Zip.

ArchCmd.PackRar(RegZipPath.FindWinRar(), Path.Combine(CurrDir, "ZipDot"), Path.Combine(Desktop, "r3xq1"));

Отлично, с этим мы закончили.


Теперь мы поговорим о классе Zipstorer.cs

Этот класс можно использовать в .NetFramework 4.0 за место всяких левых библиотек. Класс сможете найти в архиве, я его немного изменил чтобы было проще использовать и добавил класс ZipR3.cs через который можно вызывать необходимые методы.

public static class ZipR3
{
        /* Created r3xq1 */
        #region Methods for adding folders to the archive | Методы для добавления папок в архив
        /// <summary>
        /// Method for adding folders to .Zip archive
        /// <br>Метод для добавления папок в .Zip архив</br>
        /// </summary>
        /// <param name="zippath">The path to the .zip archive folder<br>Путь к папке .zip архива</br></param>
        /// <param name="datapath">Full path to folders to add to .zip archive<br>Полный путь к папкам для добавления в .zip архив</br></param>
        /// <param name="mode">Compression method<br>Метод сжатия</br></param>
        /// <param name="commentzip">Comments on the .zip archive<br>Комментарии к .zip архиву</br></param>
        public static void AddMassDirectory(string zippath, string[] datapath, ZipStorer.Compression mode, string commentzip = "") 
        {
            using var zipdir = ZipStorer.Create(zippath, commentzip);
            foreach (string dir in datapath.Where(dir => Directory.Exists(dir)))
            {
                zipdir?.AddDirectory(mode, dir, string.Empty);
            }
        }
        public static void AddMassDirectory(string zippath, List<string> datapath, ZipStorer.Compression mode, string commentzip = "")
        {
            using var zipdir = ZipStorer.Create(zippath, commentzip);
            foreach (string dir in datapath.Where(dir => Directory.Exists(dir)))
            {
                zipdir?.AddDirectory(mode, dir, string.Empty);
            }
        }
        /// <summary>
        /// <br>Метод для добавления папки в .Zip архив</br>
        /// </summary>
        /// <param name="zippath">The path to the .zip archive folder<br>Путь к папке .zip архива</br></param>
        /// <param name="datapath">Full path to the folder to add to the .zip archive<br>Полный путь к папке для добавления в .zip архив</br></param>
        /// <param name="mode">Compression method<br>Метод сжатия</br></param>
        /// <param name="commentzip">Comments on the .zip archive<br>Комментарии к .zip архиву</br></param>
        public static void AddDirectory(string zippath, string datapath, ZipStorer.Compression mode, string commentzip = "") 
        {
            using var zipdir = ZipStorer.Create(zippath, commentzip);
            if (Directory.Exists(datapath))
            {
                zipdir?.AddDirectory(mode, datapath, string.Empty);
            }
        }
        #endregion
        #region Methods for adding files to the archive | Методы для добавления файлов в архив
        /// <summary>
        /// Method for adding a files to a .zip archive
        /// <br>Метод для добавления файлов в .zip архив</br>
        /// </summary>
        /// <param name="zippath">The path to the .zip archive folder<br>Путь к папке .zip архива</br></param>
        /// <param name="filepath">Full path to files to add to .zip archive<br>Полный путь к файлам для добавления в .zip архив</br></param>
        /// <param name="mode">Compression method<br>Метод сжатия</br></param>
        /// <param name="commentzip">Comments on the .zip archive<br>Комментарии к .zip архиву</br></param>
        public static void AddMassFile(string zippath, string[] filepath, ZipStorer.Compression mode, string commentzip = "")
        {
            using var zip = ZipStorer.Create(zippath, commentzip);
            zip.EncodeUTF8 = true;
            foreach (string files in filepath.Where(files => File.Exists(files)))
            {
                zip?.AddFile(mode, files, Path.GetFileName(files), string.Empty);
            }
        }
        public static void AddMassFile(string zippath, List<string> filepath, ZipStorer.Compression mode, string commentzip = "")
        {
            using var zip = ZipStorer.Create(zippath, commentzip);
            zip.EncodeUTF8 = true;
            foreach (string files in filepath.Where(files => File.Exists(files)))
            {
                zip?.AddFile(mode, files, Path.GetFileName(files), string.Empty);
            }
        }
        /// <summary>
        /// Method for adding a file to a .zip archive
        /// <br>Метод для добавления файла в .zip архив</br>
        /// </summary>
        /// <param name="zippath">The path to the .zip archive folder<br>Путь к папке .zip архива</br></param>
        /// <param name="filepath">Full path to the file to add to the .Zip archive<br>Полный путь к файлу для добавления в .Zip архив</br></param>
        /// <param name="mode">Compression method<br>Метод сжатия</br></param>
        /// <param name="commentzip">Comments on the .zip archive<br>Комментарии к .zip архиву</br></param>
        public static void AddFile(string zippath, string filepath, ZipStorer.Compression mode, string commentzip = "")
        {
            using var zip = ZipStorer.Create(zippath, commentzip);
            zip.EncodeUTF8 = true;
            zip?.AddFile(mode, filepath, Path.GetFileName(filepath), string.Empty);
        }
        #endregion
        #region Methods for unpacking files from the archive | Методы для распаковки файлов из архива
        /// <summary>
        /// Method for unpacking a files from a .Zip archive
        /// <br>Метод для распаковки файлов из .Zip архива</br>
        /// </summary>
        /// <param name="zippath">The path to the .zip archive folder<br>Путь к папке .zip архива</br></param>
        /// <param name="filenames">Name of files to unzip<br>Имя файлов которые нужно распаковать</br></param>
        /// <param name="savepath">Path to save files<br>Путь для сохранения файлов</br></param>
        public static void UnpackMassFile(string zippath, string[] filenames, string savepath)
        {
            using var zip = ZipStorer.Open(zippath, FileAccess.Read);
            foreach (ZipStorer.ZipFileEntry entry in zip.ReadCentralDir())
            {
                foreach (string file in filenames.Where(file => Path.GetFileName(entry.FilenameInZip).Contains(file)))
                {
                    zip?.ExtractFile(entry, Path.Combine(savepath, file));
                }
            }
        }
        /// <summary>
        /// Method for unpacking a file from a .Zip archive
        /// <br>Метод для распаковки файла из .Zip архива</br>
        /// </summary>
        /// <param name="zippath">The path to the .zip archive folder<br>Путь к папке .zip архива</br></param>
        /// <param name="filename">The name of the file you want to unzip<br>Имя файла которого нужно распаковать</br></param>
        /// <param name="savepath">Path to save file<br>Путь для сохранения файла</br></param>
        public static void UnpackFile(string zippath, string filename, string savepath)
        {
            using var zip = ZipStorer.Open(zippath, FileAccess.Read);
            foreach (ZipStorer.ZipFileEntry entry in zip.ReadCentralDir().Where(entry => Path.GetFileName(entry.FilenameInZip).Contains(filename)))
            {
                zip?.ExtractFile(entry, Path.Combine(savepath, filename));
                break;
            }
        }
        #endregion
    }

Класс можете изменить под себя, как вам будет удобно.


В версии .NetFramework 4.5 имеется встроенный архиватор который вы можете использовать.

Для этого подключите ссылки:

  • using System
  • System.IO.Compression
  • System.IO.Compression.FileSystem

Теперь запишем метод который добавляет файлы в архив .Zip

/// <summary>
/// Метод для добавления файла в .Zip архив
/// </summary>
/// <param name="zipfile">Полный путь к .Zip архиву</param>
/// <param name="inputfile">Путь к файлу для добавления в .Zip архив</param>
/// <param name="compressionlevel">Метод сжатия</param>
public static void AddFileInZip(string zipfile, string inputfile, CompressionLevel compressionlevel)
{
  try
  {
     using ZipArchive za = ZipFile.Open(zipfile, ZipArchiveMode.Update);
     za?.CreateEntryFromFile(inputfile, Path.GetFileName(inputfile), compressionlevel);
  }
  catch (Exception ex) { throw new Exception("Ошибка: ", ex); }
}

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

private static readonly string Desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
private static readonly string TargetFile = Path.Combine(Desktop, "11.jpg");
AddFileInZip("r3xq1.zip", TargetFile, CompressionLevel.Fastest);

Можно так же использовать сторонние библиотеки для архивации, вот некоторые из них:

Примеры их использования куча, вы можете посмотреть реализации их методов на: SO - StackOverFlow CyberForum

На этом можно кончить и закончить.


Если у Вас есть желание поблагодарить меня небольшой суммой я буду только рад

BTC: 1HVjr2GmsTeRKG78rLxmX4CeQBEH8fUAhR

По всем вопросами пишите мне в:

https://github.com/r3xq1