当前位置: 首页 > 知识库问答 >
问题:

使用Apache Commons压缩库以非机器依赖的方式向Tar存档添加文件和库

樊胜
2023-03-14

我正在处理一个应用程序,它需要创建一个tar归档,以便计算他的散列。但我遇到了一些问题:

  • 不同计算机的tar不相同,则计算的哈希也不同
  • 无法正确添加目录
  • 如果我在tar的末尾添加了一个zip文件,那么我就可以从zip文件中获取内容:/

有没有人能找到我的代码不正确的地方?

    public static File createTarFile(File[] files, File repository) {
    File tarFile = new File(TEMP_DIR + File.separator + repository.getName() + Constants.TAR_EXTENSION);
    if (tarFile.exists()) {
        tarFile.delete();
    }

    try {
        OutputStream out = new FileOutputStream(tarFile);

        TarArchiveOutputStream aos = (TarArchiveOutputStream) new ArchiveStreamFactory().createArchiveOutputStream("tar", out);

        for(File file : files){
            Utilities.addFileToTar(aos, file, "");
        }

        aos.finish();
        aos.close();
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return tarFile;
}

private static void addFileToTar(TarArchiveOutputStream tOut, File file, String base) throws IOException {

    TarArchiveEntry entry = new TarArchiveEntry(file, base + file.getName());
    entry.setModTime(0);
    entry.setSize(file.length());
    entry.setUserId(0);
    entry.setGroupId(0);
    entry.setUserName("avalon");
    entry.setGroupName("excalibur");
    entry.setMode(0100000);
    entry.setSize(file.length());
    tOut.putArchiveEntry(entry);

    if (file.isFile()) {
        IOUtils.copy(new FileInputStream(file), tOut);
        tOut.closeArchiveEntry();
    } else {
        tOut.closeArchiveEntry();
        File[] children = file.listFiles();
        if (children != null) {
            for (File child : children) {
                addFileToTar(tOut, child, file.getName());
            }
        }
    }
}

谢谢你。

共有1个答案

寿鸣
2023-03-14

在看了caarlos0的帖子后终于找到了解决方法:在Linux上用Apache Commons压缩压缩文件时的编码问题

使用apache-commons-1.8.jar库,我制作了一个工具类来完成这项工作:

您可以在这里找到这段代码:库MakeTar的GitHub存储库

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;

/**
 * The Class TarArchive.
 */
public class TarArchive {

    /**
     * Creates the tar of files.
     *
     * @param files the files
     * @param tarPath the tar path
     * @throws IOException Signals that an I/O exception has occurred.
     */
    public static void createTarOfFiles(String[] files, String tarPath) throws IOException
    {
        FileOutputStream fOut = null;
        BufferedOutputStream bOut = null;
        TarArchiveOutputStream tOut = null;

        Arrays.sort(files);
        try
        {
            fOut = new FileOutputStream(new File(tarPath));
            bOut = new BufferedOutputStream(fOut);
            tOut = new TarArchiveOutputStream(bOut);

            for (String file : files) {
                addFileToTar(tOut, file, "");
            }
        }
        finally
        {
            tOut.finish();
            tOut.close();
            bOut.close();
            fOut.close();
        }
    }

    /**
     * Creates the tar of directory.
     *
     * @param directoryPath the directory path
     * @param tarPath the tar path
     * @throws IOException Signals that an I/O exception has occurred.
     */
    public static void createTarOfDirectory(String directoryPath, String tarPath) throws IOException
    {
        FileOutputStream fOut = null;
        BufferedOutputStream bOut = null;
        TarArchiveOutputStream tOut = null;

        try
        {
            fOut = new FileOutputStream(new File(tarPath));
            bOut = new BufferedOutputStream(fOut);
            tOut = new TarArchiveOutputStream(bOut);

            addFileToTar(tOut, directoryPath, "");
        }
        finally
        {
            tOut.finish();
            tOut.close();
            bOut.close();
            fOut.close();
        }
    }

    /**
     * Adds the file to tar.
     *
     * @param tOut the t out
     * @param path the path
     * @param base the base
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void addFileToTar(TarArchiveOutputStream tOut, String path, String base) throws IOException
    {
        File f = new File(path);
        String entryName = base + f.getName();
        TarArchiveEntry tarEntry = new TarArchiveEntry(f, entryName);

        tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);

        if(f.isFile())
        {
           tarEntry.setModTime(0);
           tOut.putArchiveEntry(tarEntry);

           IOUtils.copy(new FileInputStream(f), tOut);

           tOut.closeArchiveEntry();
        }
        else
        {
            File[] children = f.listFiles();
            Arrays.sort(children);

            if(children != null)
            {
                for(File child : children)
                {
                    addFileToTar(tOut, child.getAbsolutePath(), entryName + "/");
                }
            }
        }
    }
}

谢谢你读我的书。

编辑:很小的修正,我已经添加了数组的种类。

编辑2:我已经更正了代码,以便在所有机器上有相同的存档。在存档上计算的哈希值在任何地方都是相同的。

 类似资料:
  • 问题内容: 我正在开发一个需要创建tar存档以计算其哈希值的应用程序。但是我遇到一些问题: tar在不同的机器上不一样,则计算出的哈希值不同 我无法正确添加目录 如果我在tar的最后添加一个zip文件,则我的zip文件中的内容不存在:/ 我已经阅读了SO中的不同文章以及有关apache的专用教程,还阅读了apache commons compress jar的源测试代码,但是我没有找到正确的解决方

  • 我正在使用Apache Commons Compress创建tar归档并解压它们。我的问题从这个方法开始:

  • 我正在为一个供应商做一个库项目,它需要Android Volley作为一个依赖项。我已经在Android Studio中使用了这个Create aar文件来创建.aar文件,并将其包含在一个测试项目中,我正在使用这个添加本地.aar文件到使用“flatdirs”的Gradle build中是不起作用的。库链接精细,项目编制无差错。但在运行时,测试应用程序崩溃,说它找不到Volley 我的图书馆项目

  • 我的GCP云存储桶中有很多.tar文件。每个.tar文件都有多个图层。我想使用GCP数据流解压缩这些.tar文件,并将它们放回另一个GCP存储桶中。 我找到了Google提供的用于批量解压缩云存储文件的实用工具模板,但它不支持.tar文件扩展名。 也许我应该在上传到云端之前尝试解压文件,或者Beam中是否存在其他内容? 每个tar文件未经压缩大约有15 TB。

  • 本文向大家介绍linux tar压缩排除某个文件夹的方法,包括了linux tar压缩排除某个文件夹的方法的使用技巧和注意事项,需要的朋友参考一下 一般直接用tar命令打包很简单,直接使用 tar -zcvf test.tar.gz test 即可。 在很多时候,我们要对某一个目录打包,而这个目录下有几十个子目录和子文件,我们需要在打包的时候排除其中1、2个目录或文件。 这时候我们在用tar命令打

  • 我看到莴苣可以为Redis序列化对象做压缩:https://lettuce.io/core/release/reference/#codecs.compression 有没有办法在Spring Boot Data LettuceConnectionFactory或其他bean中设置此配置?我在这里也看到了这样一个问题:https://github.com/lettuce-io/lettuce-co