browse by category or date

I’ve came across a number of compression libraries in .NET world. At first, I used DotNetZip. DotNetZip supports only Zip format. But it was sufficient. Later, I found SharpZipLib. SharpZipLib supports more format such as Gzip, Tar and Bzip2.

SharpCompress supersedes both of them. As of now, it able to extract these formats:

  1. RAR
  2. 7Zip
  3. Zip
  4. Tar
  5. BZip2
  6. GZip

Currently it able to write archive in these formats:

  1. Zip
  2. Tar
  3. BZip2
  4. GZip

The following are not yet supported, and it’s in To-Do list:

  1. RAR 5
  2. Write 7Zip
  3. Zip64
  4. Multi-volume Zip

To install SharpCompress, you can manually fork the repository from GitHub. Or you can use NuGet:

     PM > Install-Package SharpCompress

Import the reference:

using SharpCompress.Archive;
using SharpCompress.Common;

Opening archive:

//f is FileInfo object     
var archive = ArchiveFactory.Open(f);

Extracting archive content:

//Sort the entries before extracting
//This will help especially when the archive contain folders
var sortedEntries = archive.Entries.OrderBy(x=>x.FilePath.Length);
foreach (var entry in sortedEntries)
{
   if (entry.IsDirectory) {
      //Create subdirectory
   }
   else {
      //extract file
      entry.WriteToFile(File_Path_Destination, Extracting_Option);
   }
}

Here’s the complete example that I made recently. This program will iterate a directory, and all of its sub-directories, then extract any .RAR or .ZIP found.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Archive;
using SharpCompress.Common;

namespace ArchiveExtractor
{
    //Extension to allow us to filter files in a folder using multiple extensions
    static class MyExtension
    {
        public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions)
        {
            if (extensions == null)
                throw new ArgumentNullException("extensions");
            IEnumerable<FileInfo> files = dir.EnumerateFiles();
            return files.Where(f => extensions.Contains(f.Extension));
        }
    }
    class Program
    {
        //Dictionary to keep track which files already processed
        private static Dictionary<String, List<String>> _processDict;
        
        static void Main(string[] args)
        {
            _processDict = new Dictionary<string, List<string>>();
            //repeat until user decide to call quit
            while (true)
            {
                Console.Write("Directory to Process (x to Exit, Enter to process current directory): ");
                var cmd = Console.ReadLine();
                
                //Setup the initial directory
                DirectoryInfo curDir = null;
                if (String.IsNullOrEmpty(cmd))
                {
                    curDir = new DirectoryInfo(Directory.GetCurrentDirectory());
                }
                else if (cmd.ToLower() == "x")
                    return;
                else
                {
                    curDir = new DirectoryInfo(cmd);
                    if (!curDir.Exists)
                    {
                        Console.WriteLine("Invalid directory");
                        continue;
                    }
                }
                //Process the directory
                ProcessDirectory(curDir, "");
            }
        }

        private static void ProcessDirectory(DirectoryInfo dir, String prefix)
        {
            Console.WriteLine("{0}[{1}]", prefix, dir.FullName);
            _processDict.Add(dir.FullName, new List<string>());

            var subdirs = dir.GetDirectories();
            foreach (var subdir in subdirs)
            {
                //Recursively process the sub-directories
                ProcessDirectory(subdir,"   ");
            }
            //In case the .ZIP extracts to .RAR,
            //process the files twice
            ProcessFiles(dir,prefix);
            ProcessFiles(dir, prefix);
        }

        private static void ProcessFiles(DirectoryInfo dir, String prefix)
        {
            foreach (var f in dir.GetFilesByExtensions(".zip", ".rar"))
            {
                //have we processed this file before?
                if (!_processDict[dir.FullName].Contains(f.Name))
                {
                    Console.WriteLine("{0}  {1}",prefix, f.Name);
                    //nope, mark it as processed
                    _processDict[dir.FullName].Add(f.Name);

                    //open Archive
                    var archive = ArchiveFactory.Open(f);
                    //sort the entries
                    var sortedEntries = archive.Entries.OrderBy(x => x.FilePath.Length);
                    foreach (var entry in sortedEntries)
                    {
                        if (entry.IsDirectory && !Directory.Exists(dir.FullName + "\\" + entry.FilePath))
                        {
                            //create sub-directory 
                            dir.CreateSubdirectory(entry.FilePath);
                        }
                        else if  (!File.Exists(dir.FullName + "\\" + entry.FilePath))
                        {
                            //extract the file
                            entry.WriteToFile(dir.FullName + "\\" + entry.FilePath, ExtractOptions.Overwrite);
                        }
                    }
                }
            }
        }
    }
}

I hope it helps, cheers!

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

A few days back, I stumbled into a superb screen capture program called ShareX. You can download it here: http://getsharex.com/. If you are curious with its source code, you can view/contribute at GitHub.

ShareX main window

ShareX has so many capture mode:
Share X capture mode

Select actions to do after capture the image:

sharex-after-capture action

Change output folder

Application Settings -> Paths:
sharex-after-capture-folder

Change Watermark

Task Settings -> Image -> Effects
sharex-image-effect
sharex-image-effect-overview

To me, what makes ShareX really stand-out is it’s upload capability. So many destinations available for uploading
sharex-upload

What I haven’t figure out is how to make ShareX upload to WordPress blog. That would save me a few minutes every time I blog. I shall investigate it in another blog post. 😀

I hope it helps, cheers!

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

I guess this is a continuation of my previous post. So yesterday I officially opened up the reverse proxy to public. Here’s the steps I took:

  1. Add the sub-domain name in our nameserver, pointing it out to one of our public IP
  2. Update the Firewall to ensure the public IP is translated to the NGINX IP address
  3. Update NGINX configuration

Everything runs smoothly except step 1. After 24 hours, the DNS correctly propagated to M1, StarHub and the rest of the Internet. But it didn’t propagated to the SingTel’s network. My colleagues which are subscribing to M1 and StarHub able to resolve the new sub-domain. One colleague which is under SingTel couldn’t. I found rather ironic, since our ISP is actually SingTel! 😛

As of the NGINX configuration, open /etc/nginx/sites-enabled/default then add something similar to below

server {
    listen       80;
    #public sub-domain name
    server_name  myNewApp.myCompany.com.sg;

    access_log  /var/log/nginx/default/myNewApp.myCompany.access.log;
    error_log /var/log/nginx/default/myNewApp.myCompany.error.log;

    # proxy to IIS backend server
    location / {
        proxy_pass         http://10.0.10.122:80/;
        proxy_redirect     off;
        #public sub-domain name
        proxy_set_header   Host             myNewApp.myCompany.com.sg;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_max_temp_file_size 0;

        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;

        proxy_buffer_size          4k;
        proxy_buffers              4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    } 
}

Yes, as simple as that. If you are interested to learn more about NGINX, you should start by reading Martin’s post.

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant: