Click here to Skip to main content
15,119,410 members
Articles / Programming Languages / C#
Posted 25 Jan 2012

Tagged as


21 bookmarked

How to compress/decompress directories using GZipStream

Rate me:
Please Sign up or sign in to vote.
4.89/5 (21 votes)
25 Jan 2012CPOL
Very simple console utility to compress/decompress directories uses GZipStream from the System.IO.Compression namespace.

The example contains four independent functions ready for copy/paste:

CompressFile(), CompressDirectory(), DecompressFile(), DecompressToDirectory()

They may inform about progress and don't contain any Console/GUI specific code due to ProgressDelegate.

The complete console utility is represented as well. The utility works in both directions. If the first parameter is a directory, then the utility stores all its content to the compressed file (second parameter). If first parameter is a compressed file, the utility restores all files to the destination directory (second parameter).

I hope it would be convenient to use.

using System;
using System.Text;
using System.IO;
using System.IO.Compression;

namespace CmprDir
  class Program
    delegate void ProgressDelegate(string sMessage);

    static void CompressFile(string sDir, string sRelativePath, GZipStream zipStream)
      //Compress file name
      char[] chars = sRelativePath.ToCharArray();
      zipStream.Write(BitConverter.GetBytes(chars.Length), 0, sizeof(int));
      foreach (char c in chars)
        zipStream.Write(BitConverter.GetBytes(c), 0, sizeof(char));

      //Compress file content
      byte[] bytes = File.ReadAllBytes(Path.Combine(sDir, sRelativePath));
      zipStream.Write(BitConverter.GetBytes(bytes.Length), 0, sizeof(int));
      zipStream.Write(bytes, 0, bytes.Length);

    static bool DecompressFile(string sDir, GZipStream zipStream, ProgressDelegate progress)
      //Decompress file name
      byte[] bytes = new byte[sizeof(int)];
      int Readed = zipStream.Read(bytes, 0, sizeof(int));
      if (Readed < sizeof(int))
        return false;

      int iNameLen = BitConverter.ToInt32(bytes, 0);
      bytes = new byte[sizeof(char)];
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < iNameLen; i++)
        zipStream.Read(bytes, 0, sizeof(char));
        char c = BitConverter.ToChar(bytes, 0);
      string sFileName = sb.ToString();
      if (progress != null)

      //Decompress file content
      bytes = new byte[sizeof(int)];
      zipStream.Read(bytes, 0, sizeof(int));
      int iFileLen = BitConverter.ToInt32(bytes, 0);

      bytes = new byte[iFileLen];
      zipStream.Read(bytes, 0, bytes.Length);

      string sFilePath = Path.Combine(sDir, sFileName);
      string sFinalDir = Path.GetDirectoryName(sFilePath);
      if (!Directory.Exists(sFinalDir))

      using (FileStream outFile = new FileStream(sFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
        outFile.Write(bytes, 0, iFileLen);

      return true;

    static void CompressDirectory(string sInDir, string sOutFile, ProgressDelegate progress)
      string[] sFiles = Directory.GetFiles(sInDir, "*.*", SearchOption.AllDirectories);
      int iDirLen = sInDir[sInDir.Length - 1] == Path.DirectorySeparatorChar ? sInDir.Length : sInDir.Length + 1;

      using (FileStream outFile = new FileStream(sOutFile, FileMode.Create, FileAccess.Write, FileShare.None))
      using (GZipStream str = new GZipStream(outFile, CompressionMode.Compress))
        foreach (string sFilePath in sFiles)
          string sRelativePath = sFilePath.Substring(iDirLen);
          if (progress != null)
          CompressFile(sInDir, sRelativePath, str);

    static void DecompressToDirectory(string sCompressedFile, string sDir, ProgressDelegate progress)
      using (FileStream inFile = new FileStream(sCompressedFile, FileMode.Open, FileAccess.Read, FileShare.None))
      using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true))
        while (DecompressFile(sDir, zipStream, progress));

    public static int Main(string[] argv) 
      if (argv.Length != 2)
        Console.WriteLine("Usage: CmprDir.exe <in_dir compressed_file> | <compressed_file out_dir>");
        return 1;

      string sDir;
      string sCompressedFile;
      bool bCompress = false;
        if (Directory.Exists(argv[0]))
          sDir = argv[0];
          sCompressedFile = argv[1];
          bCompress = true;
          if (File.Exists(argv[0]))
            sCompressedFile = argv[0];
            sDir = argv[1];
            bCompress = false;
            Console.Error.WriteLine("Wrong arguments");
            return 1;

        if (bCompress)
          CompressDirectory(sDir, sCompressedFile, (fileName) => { Console.WriteLine("Compressing {0}...", fileName); });
          DecompressToDirectory(sCompressedFile, sDir, (fileName) => { Console.WriteLine("Decompressing {0}...", fileName); });

        return 0;
      catch (Exception ex)
        return 1;


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Andrew Novik
Web Developer
United States United States
Programmer since 1990.

Comments and Discussions

PraiseWorks like a charm Pin
Tech Code Freak15-Sep-19 4:08
MemberTech Code Freak15-Sep-19 4:08 
Questionsystem.outOfMemory Exception Pin
Member 312041427-Feb-17 22:14
MemberMember 312041427-Feb-17 22:14 
BugReg:Directory Compression Pin
Member 110323613-Apr-15 19:49
MemberMember 110323613-Apr-15 19:49 
QuestionI unzipped manually and got a file with no extension Pin
Kumar Tanmay23-Dec-14 0:12
MemberKumar Tanmay23-Dec-14 0:12 
AnswerRe: I unzipped manually and got a file with no extension Pin
Andrew Novik23-Dec-14 7:27
MemberAndrew Novik23-Dec-14 7:27 
GeneralNice Code Pin
Аslam Iqbal31-Jan-14 3:50
professionalАslam Iqbal31-Jan-14 3:50 
GeneralMy vote of 5 Pin
Thé Dèvíl 201312-Apr-13 3:11
MemberThé Dèvíl 201312-Apr-13 3:11 
GeneralMy vote of 5 Pin
David Catriel6-Mar-13 11:54
MemberDavid Catriel6-Mar-13 11:54 
QuestionProblem getting this to work. Pin
Tom Cusick8-Feb-13 10:45
MemberTom Cusick8-Feb-13 10:45 
AnswerRe: Problem getting this to work. Pin
Andrew Novik11-Feb-13 6:46
MemberAndrew Novik11-Feb-13 6:46 
QuestionHow to compree directories? Pin
Ar.Gorgin30-Sep-12 19:57
MemberAr.Gorgin30-Sep-12 19:57 
GeneralDotNet zip can do security attributes and encryption and gen... Pin
Dean Oliver1-Feb-12 9:12
MemberDean Oliver1-Feb-12 9:12 
GeneralReason for my vote of 1 a bit unnecessary there are api's th... Pin
Dean Oliver31-Jan-12 19:33
MemberDean Oliver31-Jan-12 19:33 
Reason for my vote of 1
a bit unnecessary there are api's that do this out the box.
GeneralRe: Thanks for the alternative - DotNetZip is pretty useful libr... Pin
Andrew Novik1-Feb-12 6:58
MemberAndrew Novik1-Feb-12 6:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.