-1

I'm new to C# and object-oriented programming in general. I am trying to create an application to extract the contents of a compressed file.

Upon searching, I found out that .NET does not by default support gz or tar files. Thus downloaded SharpZipLib. I went through the mentioned examples.

The following is the code:

static void Main(string[] args)
{
    List<string> fileList = new List<string>();
    List<string> targzList = new List<string>();

    Console.WriteLine("Begin Extracting?");
    var ch = Console.ReadLine();
    if (ch == "y")
    {
        Console.WriteLine("Extracting The Zip {0}", zipFilePath);
        ExtractZipFile(zipFilePath, null, destinationPath);
        Console.WriteLine("Extraction Finished...");
        foreach (string file in Directory.GetFiles(destinationPath))
        {

            fileList.Add(file);
        }
    }
    Console.WriteLine("The following are the files in directory");
    foreach (string file in fileList)
    {
        Console.WriteLine(file);
    }

    Console.WriteLine("Extract All The Files?");
    var cht = Console.ReadLine();
    if (cht == "y")
    {
        foreach(var file in fileList)
        {
            if(Path.GetFileNameWithoutExtension(file).Contains("tar"))
            {
                targzList.Add(file);
                ExtractTGZ(file,Path.GetDirectoryName(file)+@"\"+Path.GetFileNameWithoutExtension(file));
            }
        }

    }



    Console.ReadLine();
}


public static void ExtractZipFile(string archiveFilenameIn, string password, string outFolder)
{
    ZipFile zf = null;
    try
    {
        FileStream fs = File.OpenRead(archiveFilenameIn);
        zf = new ZipFile(fs);
        if (!String.IsNullOrEmpty(password))
        {
            zf.Password = password;     // AES encrypted entries are handled automatically
        }
        foreach (ZipEntry zipEntry in zf)
        {
            if (!zipEntry.IsFile)
            {
                continue;           // Ignore directories
            }
            String entryFileName = zipEntry.Name;
            // to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
            // Optionally match entrynames against a selection list here to skip as desired.
            // The unpacked length is available in the zipEntry.Size property.

            byte[] buffer = new byte[4096];     // 4K is optimum
            Stream zipStream = zf.GetInputStream(zipEntry);

            // Manipulate the output filename here as desired.
            String fullZipToPath = Path.Combine(outFolder, entryFileName);
            string directoryName = Path.GetDirectoryName(fullZipToPath);
            if (directoryName.Length > 0)
                Directory.CreateDirectory(directoryName);

            // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
            // of the file, but does not waste memory.
            // The "using" will close the stream even if an exception occurs.
            using (FileStream streamWriter = File.Create(fullZipToPath))
            {
                StreamUtils.Copy(zipStream, streamWriter, buffer);
            }
        }
    }
    finally
    {
        if (zf != null)
        {
            zf.IsStreamOwner = true; // Makes close also shut the underlying stream
            zf.Close(); // Ensure we release resources
        }
    }
}

public static void ExtractTGZ(String gzArchiveName, String destFolder)
{

    Stream inStream = File.OpenRead(gzArchiveName);
    Stream gzipStream = new GZipInputStream(inStream);

    TarArchive tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
    tarArchive.ExtractContents(destFolder);
    tarArchive.Close();

    gzipStream.Close();
    inStream.Close();
}

public static void ExtractGZip(string gzipFileName, string targetDir)
{

    // Use a 4K buffer. Any larger is a waste.    
    byte[] dataBuffer = new byte[4096];

    using (System.IO.Stream fs = new FileStream(gzipFileName, FileMode.Open, FileAccess.Read))
    {
        using (GZipInputStream gzipStream = new GZipInputStream(fs))
        {

            // Change this to your needs
            string fnOut = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(gzipFileName));

            using (FileStream fsOut = File.Create(fnOut))
            {
                StreamUtils.Copy(gzipStream, fsOut, dataBuffer);
            }
        }
    }
}

The file could be a zip, gz, tar or tar.gz file. It can in turn contain multiple zip or gz or tar.gz files. All the contents of the compressed file to be extracted until no compressed file is left in any directory or sub-directory.

The structure is like following

foo.zip or foo.tar.gz
 ├───bar1.tar.gz
 │   ├───foobar1.tar
 │              ├───foobarr2.tar.gz
 ├───bar2.tar.gz
 │   ├───foobar2.tar
 │                  ├───foobarr2.zip
 ├───bar3.tar.gz
 │   ├───foobar3.tar
 ├───bar4.tar.gz
 │   ├───foobar4.tar
 ├───bar5.tar.gz
 │   ├───foobar5.tar
 ├───bar6.tar.gz
 │   ├───foobar6.tar
 |   ..........
 |   ..........
 |   ..........
 |   20+ of them

Got the solution, check my answer.

Thanks

Tango
  • 386
  • 1
  • 6
  • 29

1 Answers1

0

With help of recursion, I was able to achieve the goal.

 public static void FindFiles (string path)
        {
            foreach(string fileName in Directory.GetFiles(path))
            {

                if (Path.GetExtension(fileName) == ".zip")
                {
                    Console.WriteLine(fileName);

                    ExtractZipFile(fileName, null, Path.GetDirectoryName(fileName) + @"\" + Path.GetFileNameWithoutExtension(fileName));
                    File.Delete(fileName);
                }
                else if(Path.GetExtension(fileName)==".gz" && Path.GetFileNameWithoutExtension(fileName).Contains("tar"))
                {
                    Console.WriteLine(fileName);

                    ExtractTGZ(fileName, Path.GetDirectoryName(fileName) + @"\" + Path.GetFileNameWithoutExtension(fileName));
                    File.Delete(fileName);

                }
                else if(Path.GetExtension(fileName)==".tar")
                {
                    Console.WriteLine(fileName);
                    ExtractTar(fileName, Path.GetDirectoryName(fileName) + @"\" + Path.GetFileNameWithoutExtension(fileName));
                    File.Delete(fileName);
                }
                else if (Path.GetExtension(fileName) == ".gz" && !(Path.GetFileNameWithoutExtension(fileName).Contains("tar")))
                {
                    Console.WriteLine(fileName);
                    ExtractGZip(fileName, Path.GetDirectoryName(fileName) + @"\" + Path.GetFileNameWithoutExtension(fileName));
                    File.Delete(fileName);
                }

                //Console.WriteLine(fileName);

            }

            foreach (string directory in Directory.GetDirectories(path))
            {
                FindFiles(directory);
            }

        }

        public static void ExtractZipFile(string archiveFilenameIn, string password, string outFolder)
        {
            ZipFile zf = null;
            try
            {
                FileStream fs = File.OpenRead(archiveFilenameIn);
                zf = new ZipFile(fs);
                if (!String.IsNullOrEmpty(password))
                {
                    zf.Password = password;     // AES encrypted entries are handled automatically
                }
                foreach (ZipEntry zipEntry in zf)
                {
                    if (!zipEntry.IsFile)
                    {
                        continue;           // Ignore directories
                    }
                    String entryFileName = zipEntry.Name;

                    byte[] buffer = new byte[4096];     // 4K is optimum
                    Stream zipStream = zf.GetInputStream(zipEntry);


                    String fullZipToPath = Path.Combine(outFolder, entryFileName);
                    string directoryName = Path.GetDirectoryName(fullZipToPath);
                    if (directoryName.Length > 0)
                        Directory.CreateDirectory(directoryName);

                    using (FileStream streamWriter = File.Create(fullZipToPath))
                    {
                        StreamUtils.Copy(zipStream, streamWriter, buffer);
                    }


                }
            }
            finally
            {
                if (zf != null)
                {
                    zf.IsStreamOwner = true; // Makes close also shut the underlying stream
                    zf.Close(); // Ensure we release resources
                }
            }
        }

        public static void ExtractTGZ(String gzArchiveName, String destFolder)
        {

            Stream inStream = File.OpenRead(gzArchiveName);
            Stream gzipStream = new GZipInputStream(inStream);

            TarArchive tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
            tarArchive.ExtractContents(destFolder);
            tarArchive.Close();

            gzipStream.Close();
            inStream.Close();
        }

        public static void ExtractTar(String tarFileName, String destFolder)
        {

            Stream inStream = File.OpenRead(tarFileName);

            TarArchive tarArchive = TarArchive.CreateInputTarArchive(inStream);
            tarArchive.ExtractContents(destFolder);
            tarArchive.Close();

            inStream.Close();
        }

        public static void ExtractGZip(string gzipFileName, string targetDir)
        {


            using (FileStream fInStream = new FileStream(gzipFileName, FileMode.Open, FileAccess.Read))
            {
                using (GZipStream zipStream = new GZipStream(fInStream, CompressionMode.Decompress))
                {

                    using (FileStream fOutStream = new FileStream(targetDir, FileMode.Create, FileAccess.ReadWrite))
                    {
                        byte[] tempBytes = new byte[4096];
                        int i;
                        while ((i = zipStream.Read(tempBytes, 0, tempBytes.Length)) != 0)
                        {
                            fOutStream.Write(tempBytes, 0, i);
                        }
                    }
                }
            }
        }
Tango
  • 386
  • 1
  • 6
  • 29
  • 1
    I don't really like the "&& Path.GetFileNameWithoutExtension(fileName).Contains("tar")" part, I would suggest using EndWith with ".tar" instead to be more precise and avoid a tar decompression of a file that has a name containing "tar". – Grégory L Apr 11 '18 at 15:04
  • @GrégoryL Thanks for the suggestion. I encountered the issue and changed the code. I will update the answer. – Tango Apr 11 '18 at 15:08