java tararchiveentry_关于TarArchiveOutputStream输出Tar中包含文件目录的结局解决方案

遇到使用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 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();

}

运行结果:

cce45cea2f68

image.png

然后解压出来的文件:

cce45cea2f68

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

}

cce45cea2f68

image.png

cce45cea2f68

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

}

cce45cea2f68

image.png

答案是肯定。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java可以使用Apache Commons Compress来解压tar.gz文件。以下是一个示例代码: ```java import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import java.io.*; public class TarGzipExample { public static void main(String[] args) throws IOException { File file = new File("example.tar.gz"); try (FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); GzipCompressorInputStream gzis = new GzipCompressorInputStream(bis); TarArchiveInputStream tais = new TarArchiveInputStream(gzis)) { TarArchiveEntry entry; while ((entry = tais.getNextTarEntry()) != null) { String name = entry.getName(); File outputFile = new File(name); if (entry.isDirectory()) { outputFile.mkdirs(); } else { outputFile.getParentFile().mkdirs(); try (OutputStream out = new FileOutputStream(outputFile); BufferedOutputStream bos = new BufferedOutputStream(out)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = tais.read(buffer)) != -1) { bos.write(buffer, 0, bytesRead); } } } } } } } ``` 在读取tar.gz文件时,文件路径可能会乱码。这是因为tar格式不支持Unicode字符集,因此在保存文件名时会使用一种转换方法。如果文件名包含非ASCII字符,那么这种转换方法可能会导致文件名乱码。要解决这个问题,可以使用`org.apache.commons.compress.archivers.tar.TarUtils.parseName()`方法来解析文件名。以下是修改后的代码: ```java import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarUtils; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import java.io.*; public class TarGzipExample { public static void main(String[] args) throws IOException { File file = new File("example.tar.gz"); try (FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); GzipCompressorInputStream gzis = new GzipCompressorInputStream(bis); TarArchiveInputStream tais = new TarArchiveInputStream(gzis)) { TarArchiveEntry entry; while ((entry = tais.getNextTarEntry()) != null) { String name = TarUtils.parseName(entry.getName(), entry.getHeader().nameBytes).toString(); File outputFile = new File(name); if (entry.isDirectory()) { outputFile.mkdirs(); } else { outputFile.getParentFile().mkdirs(); try (OutputStream out = new FileOutputStream(outputFile); BufferedOutputStream bos = new BufferedOutputStream(out)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = tais.read(buffer)) != -1) { bos.write(buffer, 0, bytesRead); } } } } } } } ``` 这个示例代码会在解压缩文件时解析文件名,并在保存文件时使用解析后的文件名。这样可以避免文件名乱码问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值