使用 Apache Commons Compress 库以非机器依赖的方式将文件和目录添加到 Tar 存档
Posted
技术标签:
【中文标题】使用 Apache Commons Compress 库以非机器依赖的方式将文件和目录添加到 Tar 存档【英文标题】:Add files and repertories to a Tar archive with Apache Commons Compress library in non machine dependent way 【发布时间】:2015-12-03 15:01:22 【问题描述】:我正在开发一个需要创建 tar 存档以计算他的哈希的应用程序。 但是我遇到了一些问题:
不同机器的tar不一样,计算出来的hash不一样 我无法正确添加目录 如果我添加一个 zip 文件,最后,在 tar 中,我的 zip 文件中的内容:/我已经阅读了 SO 中的不同帖子和关于 apache 的专用教程,以及 apache commons compress jar 的源测试代码,但我没有得到正确的解决方案。
有没有人能找到我的代码不正确的地方?
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());
谢谢。
【问题讨论】:
档案有什么不同?我可以猜测条目的顺序是不同的,因为listFiles
可能会以不同的顺序返回文件。或者它可能是文件名的编码。您不应该设置大小,TarEntry
的构造函数已经这样做了(这可能是添加 dirs 失败的原因,length
很可能会为 dirs 返回 > 0)。添加 zip 文件时,除了添加 zip 的内容之外,您还期望什么?
【参考方案1】:
看了caarlos0的帖子终于找到了解决办法:Encoding problem when compressing files with Apache Commons Compression on Linux
使用 apache-commons-1.8.jar 库,我制作了一个可以完成这项工作的工具类:
您可以在此处找到此代码:GitHub repository of the library MakeTar
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:我已经更正了代码,以便在所有机器上拥有相同的存档。在存档上计算的哈希值在任何地方都是相同的。
【讨论】:
以上是关于使用 Apache Commons Compress 库以非机器依赖的方式将文件和目录添加到 Tar 存档的主要内容,如果未能解决你的问题,请参考以下文章
使用 org.apache.commons.validator 验证 IBAN