title: How to extract tar.gz including multi byte characters and prohibited characters on windows
body: <p>I tried to extract the tar.gz using the following libraries, but none of them work perfectly.<br>
  The environment where I create tar.gz is linux, and the environment where I extract is windows.<br>
  And I cannot touch the linux server because the server is other company's.</p>
  
  <p>M: Multi byte characters<br>
  W: Windows prohibited characters(: ;     / \（¥）| , * ?  " ＜  ＞)<br></p>
  
  <p>SharpZiplib (C#)<br>
    M: NG<br>
    W: Can replace prohibited characters to other characters<br></p>
  
  <pre><code>                Stream st = new GZipInputStream(File.OpenRead(attFile));
                  TarArchive archive = TarArchive.CreateInputTarArchive(st, TarBuffer.DefaultBlockFactor);
                  archive.SetKeepOldFiles(false);
                  archive.AsciiTranslate = false;
                  archive.SetUserInfo(0, "", 0, "None");
                  Directory.CreateDirectory(Work);
                  archive.ExtractContents(Work);
                  archive.Close();
  </code></pre>
  
  <p>tar32.dll (C#)<br>
    M: OK<br>
    W: the data isn't generated<br></p>
  
  <pre><code>    public static void ExtractTarWithDLL(string Targzpath)
      {
          IntPtr i = new IntPtr();
          string szCmdLine = "-x " + Targzpath + " -o " + Path.GetDirectoryName(Targzpath);
          Console.WriteLine(Path.GetDirectoryName(Targzpath));
          StringBuilder error = new StringBuilder(512);
  
          Tar(i, szCmdLine, error, 512);
      }
  </code></pre>
  
  <p>tar-cs (C#)<br>
    M: NG<br>
    W: Can replace prohibited characters to other characters<br></p>
  
  <pre><code>    /// &lt;summary&gt;
      /// Example of tar-cs library usage to extract tar.gz-archives.
      /// Please use the latest version (from trunk) of the library.
      /// &lt;/summary&gt;
      public static class TarGZip
      {
          public static void Extract(string inputFile, string outputDirectory)
          {
              using (FileStream inputStream = File.OpenRead(inputFile))
              using (Stream tarStream = UnGZipSteam(inputStream))
              {
                  var tarReader = new TarReader(tarStream);
                  while (tarReader.MoveNext(false)) // Moves pointer to the next file in the tar archive.
                  {
                      ExtractTarEntry(tarReader, outputDirectory);
                  }
              }
          }
  
          /// &lt;summary&gt;
          /// Since GZipStream.Position Property is not implemented,
          /// it is necessary to use MemoryStream as intermediate storage.
          /// &lt;/summary&gt;
          /// &lt;param name="inputStream"&gt;The input stream.&lt;/param&gt;
          /// &lt;returns&gt;Un-gzipped stream.&lt;/returns&gt;
          private static Stream UnGZipSteam(Stream inputStream)
          {
              using (GZipStream gZipStream = new GZipStream(inputStream, CompressionMode.Decompress))
              {
                  MemoryStream memoryStream = new MemoryStream();
                  gZipStream.CopyTo(memoryStream);
                  memoryStream.Position = 0;
                  return memoryStream;
              }
          }
  
          private static void ExtractTarEntry(TarReader tarReader, string outputDirectory)
          {
              string relativePath = tarReader.FileInfo.FileName;
  
              // Relative path can contain slash, not backslash.
              // Use Path.GetFullPath() method to convert path.
              //relativePath = relativePath.Replace('?','');
              string fullPath = Path.GetFullPath(Path.Combine(outputDirectory, relativePath));
              //string fullPath = Path.GetFullPath(Path.Combine(outputDirectory, "windows.txt"));
  
              switch (tarReader.FileInfo.EntryType)
              {
                  case EntryType.File:
                  case EntryType.FileObsolete:
                      using (FileStream outputStream = File.Create(fullPath))
                      {
                          // Read data from a current file to a Stream.
                          tarReader.Read(outputStream);
                      }
                      break;
                  case EntryType.Directory:
                      Directory.CreateDirectory(fullPath);
                      break;
                  default:
                      throw new NotSupportedException("Not supported entry type: " + tarReader.FileInfo.EntryType);
              }
          }
      }
  </code></pre>
  
  <p>tarlib (C++)<br>
    M: the data isn't generated<br>
    W: the data isn't generated<br>
  I'm using this sample code. <a href="http://www.codeproject.com/Articles/470999/tarlib-Windows-TAR-Library" rel="nofollow">http://www.codeproject.com/Articles/470999/tarlib-Windows-TAR-Library</a></p>
  
  <p>ant.jar (java)<br>
    M: By default, multi byte characters are replaced to '_'<br>
    W: throws java.io.FileNotFoundException<br></p>
  
  <pre><code>public class Targz {
  
  public void extract(Path path) throws IOException {
  
  
      if(!path.toString().endsWith(".tar.gz")){
          throw new Error("extension must be tar.gz.");
      }
  
      TarInputStream tin = new TarInputStream(new GZIPInputStream(new FileInputStream(path.toFile())));
  
      for(TarEntry tarEnt = tin.getNextEntry(); tarEnt != null; tarEnt = tin.getNextEntry()) {
          if(tarEnt.isDirectory()){
              new File(tarEnt.getName()).mkdir();
          }
          else {
              FileOutputStream fos = new FileOutputStream(new File(tarEnt.getName()));
              tin.copyEntryContents(fos);
          }
      }
      tin.close();
  } 
  </code></pre>
  
  <p>}</p>
  
  <p>Can anyone help me, please? Thanks.</p>