美文网首页
关于TarArchiveOutputStream输出Tar中包含

关于TarArchiveOutputStream输出Tar中包含

作者: Pasca | 来源:发表于2019-12-12 16:53 被阅读0次

遇到使用TarArchiveEntry的来输出tar文件,发现会带入文件的目录。解决办法就是指定这个文件的文件名称(注意:文件名称不带反斜杠这种文件层级保留字符)就可以解决问题。

TarArchiveEntry tae = new TarArchiveEntry(file, file.getName());

想要看具体思路的可以往下读,不想的就可以走了。

今天做Java将若干个文件归档为tar时。使用了org.apache.commons:commons-compress:1.19,下面是代码:

/**
     * @param files   文件列表
     * @param tarFile 输出文件
     * @return void
     * @author Benjamin
     * @description [**将列表文件归档成Tar包**]
     * @date 15:09 2019/12/12
     * @version 1.0
     **/
    public static void tarArchiveFiles(List<File> files, File tarFile) throws IOException {
        TarArchiveOutputStream taos = new TarArchiveOutputStream(new FileOutputStream(tarFile));
        System.out.println("目标Tar文件:" + tarFile.getPath());
        for (File off : files) {
            System.out.println("将要加入的文件:" + off.getPath());
            FileInputStream fis = new FileInputStream(off);
            TarArchiveEntry tae = new TarArchiveEntry(off);
            tae.setSize(off.length());
            taos.putArchiveEntry(tae);
            IOUtils.copy(fis, taos);
            fis.close();
            taos.flush();
            taos.closeArchiveEntry();
        }
        taos.close();
    }

运行结果:


image.png

然后解压出来的文件:


image.png
可以看到,第一个文件他把文件的父路径一起打包进去了。然而我们这边的业务要求是不打包父路径。找遍了他的方法都没看到怎么设置不打包父路径的代码。度娘了半天也没看到。(全是粘贴复制)
静下心来,看了看源码,突然发现有这样的代码:
//gou构造方法,我调用的是这个方法
public TarArchiveEntry(File file) {
        //获取了当前文件的路径,来作为文件名
        this(file, file.getPath());
    }
    //最终都是调用这个构造方法
    public TarArchiveEntry(File file, String fileName) {
        this.name = "";
        this.userId = 0L;
        this.groupId = 0L;
        this.size = 0L;
        this.linkName = "";
        this.magic = "ustar\u0000";
        this.version = "00";
        this.groupName = "";
        this.devMajor = 0;
        this.devMinor = 0;
        this.extraPaxHeaders = new HashMap();
        String normalizedName = normalizeFileName(fileName, false);
        ....略...
    }

从上面可以看到,当我们创建TarArchiveEntry对象的时候,如果不传入文件名称,他就会使用当前文件的路径作为名称。在tar文件中,你的文件就是/xxx/xxx/xxx/xxx.jpg。当你解压的时候/xxx/xxx/xxx/就会变为文件夹。于是乎,开始实验。直接TarArchiveEntry(File file, String fileName) 来指定不含路径 的名称。

/**
     * @param files   文件列表
     * @param tarFile 输出文件
     * @return void
     * @author Benjamin
     * @description [**将列表文件归档成Tar包**]
     * @date 15:09 2019/12/12
     * @version 1.0
     **/
    public static void tarArchiveFiles(List<File> files, File tarFile) throws IOException {
        TarArchiveOutputStream taos = new TarArchiveOutputStream(new FileOutputStream(tarFile));
        System.out.println("目标Tar文件:" + tarFile.getPath());
        for (File off : files) {
            System.out.println("将要加入的文件:" + off.getPath());
            FileInputStream fis = new FileInputStream(off);
            TarArchiveEntry tae = new TarArchiveEntry(off, off.getName());
            tae.setSize(off.length());
            taos.putArchiveEntry(tae);
            IOUtils.copy(fis, taos);
            fis.close();
            taos.flush();
            taos.closeArchiveEntry();
        }
        taos.close();
    }
image.png
image.png
可以看到,已经没有上级文件夹了。于是这个问题就解决了。
如果不想带有路径,则调用TarArchiveEntry(File file, String fileName) l来为文件指定一个名称
扩展一下,既然他是根据文件名称来解压,我们是不是也可以在文件名称前面加上文件夹的名称,来达到自定义里面的文件层级呢?
/**
     * @param files   文件列表
     * @param tarFile 输出文件
     * @return void
     * @author Benjamin
     * @description [**将列表文件归档成Tar包**]
     * @date 15:09 2019/12/12
     * @version 1.0
     **/
    public static void tarArchiveFiles(List<File> files, File tarFile) throws IOException {
        TarArchiveOutputStream taos = new TarArchiveOutputStream(new FileOutputStream(tarFile));
        System.out.println("目标Tar文件:" + tarFile.getPath());
        for (File off : files) {
            System.out.println("将要加入的文件:" + off.getPath());
            FileInputStream fis = new FileInputStream(off);
            TarArchiveEntry tae = new TarArchiveEntry(off, "新建文件夹" + File.separator + off.getName());
            tae.setSize(off.length());
            taos.putArchiveEntry(tae);
            IOUtils.copy(fis, taos);
            fis.close();
            taos.flush();
            taos.closeArchiveEntry();
        }
        taos.close();
    }
image.png

答案是肯定。

相关文章

  • 关于TarArchiveOutputStream输出Tar中包含

    遇到使用TarArchiveEntry的来输出tar文件,发现会带入文件的目录。解决办法就是指定这个文件的文件名称...

  • RHCSA题解(十五) - 创建指定的备份文件

    创建名为/root/backup.tar.bz2的备份文件,其中包含/usr/local的内容,tar 必须使用 ...

  • 一些实用的生信单行命令

    基本awk和sed命令 从文件中提取2,4,5列: 输出第五列中包含abc123的行: 输出第五列中不包含abc1...

  • 资源覆盖

    filter 判断变量VARIANTS中是否包含word1和 word2,如果包含,则取出包含的值 示例: 输出结...

  • Linux压缩及解压缩命令

    tar -c:创建一个归档文件-C:执行 tar 命令前切换到指定目录-f:其后指定归档文件的名称-v:输出详细信...

  • 常用库函数

    输出函数: (1)printf函数:printf函数是格式输出函数,其函数原型包含在头文件”stdio.h”中.格...

  • tar常用命令

    tar 命令中的.tar 、.tar.gz 、.gz、.xz压缩解压 .tar只是进行打包,并没有压缩。 可用ta...

  • Linux常用命令

    (持续更新中......) 1、tar命令: (1)解压:tar -zxvf 待解压包 例如:tar -zxvf ...

  • shell-15 shell对输出流的处理 awk

    在日常计算机管理中,总会有很多数据输出到屏幕或者文件,这些输出包含了标准输出、标准错误输出。默认情况下,这些信息全...

  • PHP学习疑难杂症

    变量当双引号中包含变量时,变量会与双引号中的内容连接在一起;当单引号中包含变量时,变量会被当做字符串输出。 ***...

网友评论

      本文标题:关于TarArchiveOutputStream输出Tar中包含

      本文链接:https://www.haomeiwen.com/subject/hsytnctx.html