如何在Windows上创建,解压,更新.tar.gz压缩包

时间:2022-07-25 16:40:03

Linux上常用的压缩包格式是.tar.gz。.tar.gz文件的创建过程有两步。首先把文件打包到tar文件中,然后用gzip压缩tar文件。这里分享下如何在Windows上创建,解压,更新.tar.gz压缩包。

Linux命令

如果在Windows上安装了Linux子系统,可以用Linux命令。
创建.tar.gz

tar -czvf dwt.tar.gz dwt/

解压.tar.gz

tar -xzvf dwt.tar.gz -C tmp/

7zip命令

创建

7z a -ttar -so dwt.tar dwt/ | 7z a -si dwt.tar.gz

解压

7z x dwt.tar.gz -so | 7z x -si -ttar

更新比较复杂

7z x dwt.tar.gz && 7z u dwt.tar dwt && del dwt.tar.gz && 7z a dwt.tar.gz dwt.tar && del dwt.tar

使用C#代码创建,解压,更新.tar.gz

下载SharpZipLib

创建

private void CreateTarGZ(string tgzFilename, string sourceDirectory)
        {
            Stream outStream = File.Create(tgzFilename);
            Stream gzoStream = new GZipOutputStream(outStream);
            TarArchive tarArchive = TarArchive.CreateOutputTarArchive(gzoStream);

            // Note that the RootPath is currently case sensitive and must be forward slashes e.g. "c:/temp"
            // and must not end with a slash, otherwise cuts off first char of filename
            // This is scheduled for fix in next release
            tarArchive.RootPath = sourceDirectory.Replace('\\', '/');
            if (tarArchive.RootPath.EndsWith("/"))
                tarArchive.RootPath = tarArchive.RootPath.Remove(tarArchive.RootPath.Length - 1);

            AddDirectoryFilesToTar(tarArchive, sourceDirectory, true, true);

            tarArchive.Close();
        }

private void AddDirectoryFilesToTar(TarArchive tarArchive, string sourceDirectory, bool recurse, bool isRoot)
        {

            // Optionally, write an entry for the directory itself.
            // Specify false for recursion here if we will add the directory's files individually.
            //
            TarEntry tarEntry;

            if (!isRoot)
            {
                tarEntry = TarEntry.CreateEntryFromFile(sourceDirectory);
                tarArchive.WriteEntry(tarEntry, false);
            }

            // Write each file to the tar.
            //
            string[] filenames = Directory.GetFiles(sourceDirectory);
            foreach (string filename in filenames)
            {
                tarEntry = TarEntry.CreateEntryFromFile(filename);
                Console.WriteLine(tarEntry.Name);
                tarArchive.WriteEntry(tarEntry, true);
            }

            if (recurse)
            {
                string[] directories = Directory.GetDirectories(sourceDirectory);
                foreach (string directory in directories)
                    AddDirectoryFilesToTar(tarArchive, directory, recurse, false);
            }
        }

解压

public 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();
        }

更新

.tar.gz解压成.tar

public string ExtractGZipFile(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);
                    }

                    return fnOut;
                }
            }
        }

更新.tar

public void UpdateTar(string tarFileName, string targetFile, bool asciiTranslate)
        {
            using (FileStream fsIn = new FileStream(tarFileName, FileMode.Open, FileAccess.Read))
            {
                string tmpTar = Path.Combine(Path.GetDirectoryName(tarFileName), "tmp.tar");
                using (FileStream fsOut = new FileStream(tmpTar, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    TarOutputStream tarOutputStream = new TarOutputStream(fsOut);
                    TarInputStream tarIn = new TarInputStream(fsIn);
                    TarEntry tarEntry;
                    while ((tarEntry = tarIn.GetNextEntry()) != null)
                    {

                        if (tarEntry.IsDirectory)
                        {
                            continue;
                        }
                        // Converts the unix forward slashes in the filenames to windows backslashes
                        //
                        string name = tarEntry.Name.Replace('/', Path.DirectorySeparatorChar);
                        string sourceFileName = Path.GetFileName(targetFile);
                        string targetFileName = Path.GetFileName(tarEntry.Name);

                        if (sourceFileName.Equals(targetFileName))
                        {
                            using (Stream inputStream = File.OpenRead(targetFile))
                            {

                                long fileSize = inputStream.Length;
                                TarEntry entry = TarEntry.CreateTarEntry(tarEntry.Name);

                                // Must set size, otherwise TarOutputStream will fail when output exceeds.
                                entry.Size = fileSize;

                                // Add the entry to the tar stream, before writing the data.
                                tarOutputStream.PutNextEntry(entry);

                                // this is copied from TarArchive.WriteEntryCore
                                byte[] localBuffer = new byte[32 * 1024];
                                while (true)
                                {
                                    int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length);
                                    if (numRead <= 0)
                                    {
                                        break;
                                    }
                                    tarOutputStream.Write(localBuffer, 0, numRead);
                                }
                            }
                            tarOutputStream.CloseEntry();
                        }
                        else
                        {
                            tarOutputStream.PutNextEntry(tarEntry);

                            if (asciiTranslate)
                            {
                                CopyWithAsciiTranslate(tarIn, tarOutputStream);
                            }
                            else
                            {
                                tarIn.CopyEntryContents(tarOutputStream);
                            }

                            tarOutputStream.CloseEntry();
                        }
                    }
                    tarIn.Close();
                    tarOutputStream.Close();
                }

                File.Delete(tarFileName);
                File.Move(tmpTar, tarFileName);
            }
        }

更新.tar.gz

private void UpdateTarGZ(string tgzFilename, string tarFileName)
        {
            Stream gzoStream = new GZipOutputStream(File.Create(tgzFilename));

            using (FileStream source = File.Open(tarFileName,
            FileMode.Open))
            {

                byte[] localBuffer = new byte[32 * 1024];
                while (true)
                {
                    int numRead = source.Read(localBuffer, 0, localBuffer.Length);
                    if (numRead <= 0)
                    {
                        break;
                    }
                    gzoStream.Write(localBuffer, 0, numRead);
                }
            }

            gzoStream.Close();

            File.Delete(tarFileName);
        }

编译

dotnet publish -c Release -r win10-x64

运行
如何在Windows上创建,解压,更新.tar.gz压缩包

源码

https://github.com/yushulx/dotnet-tar-gzip