如何在 C# 中创建 tar.gz 文件

How to create tar.gz file in C#


我试过 SevenZipLib and SevenZipSharp,但没有成功。 有人可以给我一个使用任何免费库将文本文件归档到 tar.gz 的工作示例吗?
我知道这不是压缩的最佳方式,但这是我的要求。

也许 NuGet 中支持 TAR 的最受欢迎的包是 SharpZipLib. Its wiki includes examples for working with tar.gz files, including creation。链接示例存档整个文件夹。

要归档单个文件,示例可以简化为:

private void CreateTarGZ(string tgzFilename, string fileName)
{
    using (var outStream = File.Create(tgzFilename))
    using (var gzoStream = new GZipOutputStream(outStream))
    using (var tarArchive = TarArchive.CreateOutputTarArchive(gzoStream))
    {
        tarArchive.RootPath = Path.GetDirectoryName(fileName);

        var tarEntry = TarEntry.CreateEntryFromFile(fileName);
        tarEntry.Name = Path.GetFileName(fileName);

        tarArchive.WriteEntry(tarEntry,true);
    }
}

本质上,您需要为每个要存储的文件夹和文件创建一个TarEntry

以下解决方案也可能有效: How to Create a Tar GZipped File in C#

我还没有测试过它,因为毕竟我不会使用 tar.gz 文件,但看起来很彻底而且人们说它有效。

不喜欢关于如何压缩 SharpZipLib 提供的目录的 examples,因为他们的方法不是将文件夹结构保留在您尝试转换为 .tgz 的目录中,而是复制文件夹路径这会导致您尝试压缩的任何目录。

例如:

如果您尝试使用名为 foo.c 的单个文件压缩 folderA(位于://filer/folder1/folderA),然后将 folderA 转换为 [=15] =],.tgz 文件中 foo.c 的路径为:

folderA.tgz/filer/folder1/foo.c

此解决方案忽略了 .tgz 中的额外文件,导致:

folderA.tgz/foo.c

using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using System.IO;

/// <summary>
/// Creates a .tgz file using everything in the sourceDirectory. The .tgz file will be titled {tgzFileName}.tgz and will be located in targetDirectory.
/// </summary>
/// <param name="sourceDirectory">Directory to compress into a .tgz</param>
/// <param name="tgzFileName">Name of .tgz file</param>
/// <param name="targetDirectory">Directory where {tgzFileName}.tgz should be located.</param>
/// <param name="deleteSourceDirectoryUponCompletion">Will delete sourceDirectory if <see langword="true"/></param>
/// <returns>Path to .tgz file</returns>
public string CreateTGZ(string sourceDirectory, string tgzFileName, string targetDirectory, bool deleteSourceDirectoryUponCompletion = false)
{
    if (!tgzFileName.EndsWith(".tgz"))
    {
        tgzFileName = tgzFileName + ".tgz";
    }
    using (var outStream = File.Create(Path.Combine(targetDirectory, tgzFileName)))
    using (var gzoStream = new GZipOutputStream(outStream))
    {
        var 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
        tarArchive.RootPath = sourceDirectory.Replace('\', '/');
        if (tarArchive.RootPath.EndsWith("/"))
        {
            tarArchive.RootPath = tarArchive.RootPath.Remove(tarArchive.RootPath.Length - 1);
        }

        AddDirectoryFilesToTGZ(tarArchive, sourceDirectory);

        if (deleteSourceDirectoryUponCompletion)
        {
            File.Delete(sourceDirectory);
        }

        var tgzPath = (tarArchive.RootPath + ".tgz").Replace('/', '\');

        tarArchive.Close();
        return tgzPath;
    }
}

private void AddDirectoryFilesToTGZ(TarArchive tarArchive, string sourceDirectory)
{
    AddDirectoryFilesToTGZ(tarArchive, sourceDirectory, string.Empty);
}

private void AddDirectoryFilesToTGZ(TarArchive tarArchive, string sourceDirectory, string currentDirectory)
{
    var pathToCurrentDirectory = Path.Combine(sourceDirectory, currentDirectory);

    // Write each file to the tgz.
    var filePaths = Directory.GetFiles(pathToCurrentDirectory);
    foreach (string filePath in filePaths)
    {
        var tarEntry = TarEntry.CreateEntryFromFile(filePath);

        // Name sets where the file is written. Write it in the same spot it exists in the source directory
        tarEntry.Name = filePath.Replace(sourceDirectory, "");

        // If the Name starts with '\' then an extra folder (with a blank name) will be created, we don't want that.
        if (tarEntry.Name.StartsWith('\'))
        {
            tarEntry.Name = tarEntry.Name.Substring(1);
        }
        tarArchive.WriteEntry(tarEntry, true);
    }

    // Write directories to tgz
    var directories = Directory.GetDirectories(pathToCurrentDirectory);
    foreach (string directory in directories)
    {
        AddDirectoryFilesToTGZ(tarArchive, sourceDirectory, directory);
    }
}