Tuesday, May 3, 2011

Extracting a tar.z file in C#

I would like to extract a file compressed in the tar.z (or .taz) format with the .NET framework. The problem is I cannot find any libraries wich support the LZW algorithm (often, zip, gzip and bzip2 are supported, and Z is not, for example in SharpZipLib).

It appears that compress (the algorithm producing .z compressed files) is quite old, maybe it's the reason why it's hard to find a library supporting it.

Do you have any idea concerning the extraction of such compressed files?

*EDIT: * So we have VB code to compress/decompress LZW files, but I have not found a C# library doing this job yet. So the question remains open.

From stackoverflow
  • Maybe this could be useful: http://community.sharpdevelop.net/forums/p/4969/14447.aspx#14447

    andynormancx : That isn't going to help, that uses GZip. The questioner is dealing with LZW/Compress, not GZip.
    OutOfBound : I already found this page, but it does not work: the author does not extract a .z compressed file, but a .gz compressed file (he uses a GZipInputStream). Algorithms are different !
  • Compress uses the LZW algorithm, there is a VB.NET implementation of it here:

    http://www.codeproject.com/KB/recipes/VB_LZW.aspx

    It would be fairly easy to convert it to C#. Combining that with the Tar code from SharpZipLib should do what you need.

    OutOfBound : ok thanks, i will try to convert this VB code into C#
  • You can import the J# libraries and use them in C#. They should handle that compression type. The pain that I've encountered is that you also have to install the J# runtime with your application.

    http://msdn.microsoft.com/en-us/magazine/cc164129.aspx

    Here is a class that I have shamelessly stolen and modified from somewhere on the Internet.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using java.util;
    using java.util.zip;
    using java.io;
    using System.IO;
    
    namespace cZip
    {
        public class cZip
        {
            public static void Zip(string zipFileName, List<string> sourceFiles)
            {
                FileOutputStream filOpStrm = new FileOutputStream(zipFileName);
                ZipOutputStream zipOpStrm = new ZipOutputStream(filOpStrm);
                FileInputStream filIpStrm = null;
                foreach (string strFilName in sourceFiles)
                {
                    filIpStrm = new FileInputStream(strFilName);
                    ZipEntry ze = new ZipEntry(Path.GetFileName(strFilName));
                    zipOpStrm.putNextEntry(ze);
                    sbyte[] buffer = new sbyte[1024];
                    int len = 0;
                    while ((len =
    
                    filIpStrm.read(buffer)) >= 0)
                    {
                        zipOpStrm.write(buffer, 0, len);
                    }
                }
                zipOpStrm.closeEntry();
                filIpStrm.close();
                zipOpStrm.close();
                filOpStrm.close();
            }
            public static void Extract(string zipFileName, string destinationPath)
            {
                ZipFile zipfile = new ZipFile(zipFileName);
                List<ZipEntry> zipFiles = GetZipFiles(zipfile);
    
                foreach (ZipEntry zipFile in zipFiles)
                {
                    if (!zipFile.isDirectory())
                    {
                        InputStream s = zipfile.getInputStream(zipFile);
                        try
                        {
                            Directory.CreateDirectory(String.Format(@"{0}\{1}", destinationPath, Path.GetDirectoryName(zipFile.getName())));
                            FileOutputStream dest = new FileOutputStream(Path.Combine(destinationPath + "\\" + Path.GetDirectoryName(zipFile.getName()), Path.GetFileName(zipFile.getName())));
                            try
                            {
                                int len = 0;
                                sbyte[] buffer = new sbyte[7168];
                                while ((len = s.read(buffer)) >= 0)
                                {
                                    dest.write(buffer, 0, len);
                                }
                            }
                            finally
                            {
                                dest.close();
                            }
                        }
                        finally
                        {
                            s.close();
                        }
                    }
                }
            }
            public static List<ZipEntry> GetZipFiles(ZipFile zipfil)
            {
                List<ZipEntry> lstZip = new List<ZipEntry>();
                Enumeration zipEnum = zipfil.entries();
                while (zipEnum.hasMoreElements())
                {
                    ZipEntry zip = (ZipEntry)zipEnum.nextElement();
                    lstZip.Add(zip);
                }
                return lstZip;
            }
        }
    
    }
    
    andynormancx : Are you 100% sure that java.util.zip handles LZW/Compress which is what the question asks for ? Googling suggests that, as its name suggests, that it handles zip and not plain LZW. Zip != LZW.
  • I finally chose to use another compression algorithm (GZIP), which is supported by most libraries.

    I think this solution is more reliable than translating VB into C#.

    Frank Krueger : Come on man, you shouldn't mark an answer as correct if it doesn't answer the question. **Your** problem may be solved, but **someone in the future** who needs to decompress Z files in C# won't benefit from the accepted answer.
    OutOfBound : Yes you're right. I unmarked it.
  • Take gzip.exe and stream the file through it in pipe. gzip -d will read .Z files correctly.

  • This should do the job http://www.chilkatsoft.com/p/p_68.asp

  • Very small, one-file open source class for reading Tar files in .NET:
    Tar in C#.

0 comments:

Post a Comment