美文网首页
关于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中包含

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