使用Java 代码实现,压缩东西到.tar.gz文件里面,或者使用代码解压.tar.gz文件
目录
- 1 问题
- 2 实现(工具类)
1 问题
使用Java 代码实现,压缩东西到.tar.gz文件里面,或者使用代码解压.tar.gz文件
2 实现(工具类)
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* 把一个目录下的所有文件和文件夹打成.tar.gz包(从当前的目录开始)
* @time 16:15
* @discription
**/
@Slf4j
public class TarUtil {
// private static void main(String[] args) throws IOException {
/**
* 把多个文件夹打成.tar.gz包(从当前的目录开始)
* @param sourceFolder 需要打成.tar.gz包的目录列表(包含目录和目录下的所有文件和文件夹)
* @param tarGzPath 打成的tar包生成的目标目录 例: D:/tmp 最终打包会在 D:/tmp目录下生成 test.tar.gz包
* @param tarGzFileName 打tar.gz包的名,例如:ide-sdk.tar.gz
*/
public static void fileListToTar(List sourceFolder, String tarGzPath, String tarGzFileName) {
TarArchiveOutputStream tarOs = null;
try {
// 遍历每一个文件的绝对路径
for(String folder : sourceFolder){
if(folder.contains("../")){
throw new FileNotFoundException("压缩的目录不存在。。。");
}
File sourceFile = new File(folder);
if (!sourceFile.exists()) {
throw new FileNotFoundException("压缩的目录不存在。。。");
}
}
// 压缩包流
tarOs = createTar(tarGzPath,tarGzFileName,tarOs);
// 遍历每一个文件的绝对路径
for(String folder : sourceFolder){
addFileListToTarGZ(folder, tarOs);
}
} catch (IOException e) {
log.info(e.getMessage());
} finally {
try {
tarOs.close();
} catch (IOException e) {
log.info(e.getMessage());
}
}
}
/**
* 把文件复制到.tar.gz包中
* @param sourceFile 需要复制的文件路径
* @param tarArchive tar包流
* @throws IOException 异常
*/
private static void addFileListToTarGZ(String sourceFile, TarArchiveOutputStream tarArchive)
throws IOException {
// 原文件绝对路径
if(sourceFile.contains("../")){
throw new FileNotFoundException("文件不存在。。。");
}
File file = new File(sourceFile);
String parent = file.getParent();
// String entryName = parent +File.separator+ file.getName();
String entryName = file.getName();
// 添加 tar ArchiveEntry
tarArchive.putArchiveEntry(new TarArchiveEntry(file, entryName));
if (file.isFile()) {
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
// 写入文件
IOUtils.copy(bis, tarArchive);
tarArchive.closeArchiveEntry();
bis.close();
}
}
/**
* 把一个目录下的所有文件和文件夹打成.tar.gz包(从当前的目录开始)
* Method :createTarFile
*
Description : 打包文件 .tar.gz
*
* @param sourceFolder 需要打成.tar.gz包的目录(包含目录和目录下的所有文件和文件夹)例:E:/aarm/test
* @param tarGzPath 打成的tar包生成的目标目录 例: D:/tmp 最终打包会在 D:/tmp目录下生成 test.tar.gz包
* @param tarGzFileName 打tar.gz包的名,例如:ide-sdk.tar.gz
*/
public static void fileToTar(String sourceFolder, String tarGzPath, String tarGzFileName) {
TarArchiveOutputStream tarOs = null;
try {
File sourceFile = new File(sourceFolder);
if (!sourceFile.exists()) {
throw new FileNotFoundException("压缩的目录不存在。。。");
}
tarOs = createTar(tarGzPath,tarGzFileName,tarOs);
String fileDir = sourceFolder.split(File.separator)[sourceFolder.split(File.separator).length-1];
String tarDir = tarGzFileName.split("\\.")[0];
String name = fileDir+"_"+tarDir;
addFilesToTarGZ(sourceFile, "", tarOs,name);
} catch (IOException e) {
log.info(e.getMessage());
} finally {
try {
tarOs.close();
} catch (IOException e) {
log.info(e.getMessage());
}
}
}
/**
* 把文件复制到.tar.gz包中
* @param file 需要复制的文件
* @param parent 父目录
* @param tarArchive tar包流
* @param tarDir 旧文件最后一级目录_包名目录
* @throws IOException 异常
*/
private static void addFilesToTarGZ(File file, String parent, TarArchiveOutputStream tarArchive,String tarDir)
throws IOException {
// 将最外层的文件夹名,默认为包名
if(parent.startsWith(tarDir.split("_")[0]+ File.separator)) {
parent = parent.replace(parent, tarDir.split("_")[1]+File.separator);
}
String entryName = parent + file.getName();
if(!parent.equals("")) {
// 添加 tar ArchiveEntry
tarArchive.putArchiveEntry(new TarArchiveEntry(file, entryName));
}
if (file.isFile()) { // 确认是否为file对象
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
// 写入文件
IOUtils.copy(bis, tarArchive);
tarArchive.closeArchiveEntry();
bis.close();
} else if (file.isDirectory()) { // 检查一个对象是否为文件夹
// 因为是个文件夹,无需写入内容,关闭即可
if(!parent.equals("")) {
tarArchive.closeArchiveEntry();
}
File[] files = file.listFiles();
if (files != null) {
// 读取文件夹下所有文件
for (File f : files) {
// 递归
addFilesToTarGZ(new File(f.getAbsolutePath()), entryName + File.separator, tarArchive,tarDir);
}
}
}
}
/**
* 创建tar包的流
* @param tarGzPath 需要复制的文件路径
* @param tarGzFileName 文件名称
* @param tarOs tar包流
* @throws IOException 异常
*/
private static TarArchiveOutputStream createTar(String tarGzPath, String tarGzFileName,TarArchiveOutputStream tarOs) throws IOException {
// 原文件绝对路径
if(tarGzPath.contains("../")){
throw new FileNotFoundException("文件不存在。。。");
}
File tarGzFile = new File(tarGzPath);
if (!tarGzFile.exists()) {
tarGzFile.mkdirs();
}
// 创建一个 FileOutputStream 到输出文件(.tar.gz)
File tarFile = new File(tarGzFile + "/" + tarGzFileName);
// File tarFile = new File(tarGzFile + tarGzFileName);
FileOutputStream fos = new FileOutputStream(tarFile);
// 创建一个 GZIPOutputStream,用来包装 FileOutputStream 对象
GZIPOutputStream gos = new GZIPOutputStream(new BufferedOutputStream(fos));
// 创建一个 TarArchiveOutputStream,用来包装 GZIPOutputStream 对象
tarOs = new TarArchiveOutputStream(gos);
// 若不设置此模式,当文件名超过 100 个字节时会抛出异常,异常大致如下:
// is too long ( > 100 bytes)
// 具体可参考官方文档:http://commons.apache.org/proper/commons-compress/tar.html#Long_File_Names
tarOs.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
return tarOs;
}
/**
* 解压.tar.gz文件
* @param sourceFile 需解压文件
* @param outputDir 输出目录
* @throws IOException
*/
public static void tartoFile(String sourceFile,String outputDir) throws IOException{
if(sourceFile.contains("../")){
throw new FileNotFoundException("文件不存在。。。");
}
TarInputStream tarIn = null;
// tar包的绝对路径
File file = new File(sourceFile);
try{
tarIn = new TarInputStream(new GZIPInputStream(new BufferedInputStream(
new FileInputStream(file))),1024 * 2);
//创建输出目录
createDirectory(outputDir,null);
TarEntry entry = null;
while( (entry = tarIn.getNextEntry()) != null ){
if(entry.isDirectory()){//是目录
entry.getName();
//创建空目录
System.out.println("解压之后是目录");
createDirectory(outputDir,entry.getName());
}else{//是文件
File tmpFile = new File(outputDir + "/" + entry.getName());
createDirectory(tmpFile.getPath() + "/",null);//创建输出目录
OutputStream out = null;
try{
out = new FileOutputStream(tmpFile);
int length = 0;
// 一次读取 2kb
byte[] b = new byte[2048];
while((length = tarIn.read(b)) != -1){
out.write(b, 0, length);
}
}catch(IOException ex){
throw ex;
}finally{
if(out!=null)
out.close();
}
}
}
}catch(IOException ex){
throw new IOException("解压归档文件出现异常",ex);
} finally{
try{
if(tarIn != null){
tarIn.close();
}
}catch(IOException ex){
throw new IOException("关闭tarFile出现异常",ex);
}
}
}
/**
* 构建目录
* @param outputDir
* @param subDir
*/
private static void createDirectory(String outputDir,String subDir){
File file = new File(outputDir);
if(!(subDir == null || subDir.trim().equals(""))){//子目录不为空
file = new File(outputDir + "/" + subDir);
}
if(!file.exists()){
if(!file.getParentFile().exists())
file.getParentFile().mkdirs();
file.mkdirs();
}
}
//文件拷贝,目标文件存在时会拷贝失败
public static void copyFile(File file, File fileTo){
try {
Files.copy(file.toPath(),fileTo.toPath());
} catch (IOException e) {
log.info(e.getMessage());
}
}
/**
*
*
Method :copyDirectory
*
Description : 复制文件夹
* 将源文件的外层目录也拷贝入新目录下
* @param sourcePathString
* @param targetPathString
*/
public static void copyDirectory(String sourcePathString,String targetPathString){
if(!new File(sourcePathString).canRead()){
System.out.println("源文件夹" + sourcePathString + "不可读,无法复制!");
}else{
// yin 本地测试,上传记得更改为一个斜杠
String endDir = sourcePathString.split(File.separator)[sourcePathString.split(File.separator).length-1];
//将源文件的外层目录也拷贝入新目录下
targetPathString = targetPathString+File.separator+endDir;
(new File(targetPathString)).mkdirs();
System.out.println("开始复制文件夹" + sourcePathString + "到" + targetPathString);
File[] files = new File(sourcePathString).listFiles();
for (File file : files) {
if (file.isFile()) {
copyFileForce(new File(sourcePathString + File.separator + file.getName()), new File(targetPathString + File.separator + file.getName()));
} else if (file.isDirectory()) {
copyDirectory(sourcePathString + File.separator + file.getName(), targetPathString);
}
}
System.out.println("复制文件夹" + sourcePathString + "到" + targetPathString + "结束");
}
}
//文件拷贝,强制覆盖目标文件
public static void copyFileForce(File file, File fileTo){
try {
Files.copy(file.toPath(),fileTo.toPath(), StandardCopyOption.REPLACE_EXISTING.REPLACE_EXISTING);
} catch (IOException e) {
log.info(e.getMessage());
}
}
//解压.tar.gz文件
public static void unTarGz(String sourceFile,String outputDir) throws IOException{
TarInputStream tarIn = null;
File file = new File(sourceFile);
try{
tarIn = new TarInputStream(new GZIPInputStream(
new BufferedInputStream(new FileInputStream(file))),
1024 * 2);
createDirectory(outputDir,null);//创建输出目录
TarEntry entry = null;
while( (entry = tarIn.getNextEntry()) != null ){
if(entry.isDirectory()){//是目录
entry.getName();
createDirectory(outputDir,entry.getName());//创建空目录
}else{//是文件
File tmpFile = new File(outputDir + "/" + entry.getName());
createDirectory(tmpFile.getParent() + "/",null);//创建输出目录
OutputStream out = null;
try{
out = new FileOutputStream(tmpFile);
int length = 0;
byte[] b = new byte[2048];
while((length = tarIn.read(b)) != -1){
out.write(b, 0, length);
}
}catch(IOException ex){
throw ex;
}finally{
if(out!=null)
out.close();
}
}
}
}catch(IOException ex){
throw new IOException("解压归档文件出现异常",ex);
} finally{
try{
if(tarIn != null){
tarIn.close();
}
}catch(IOException ex){
throw new IOException("关闭tarFile出现异常",ex);
}
}
}
}
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/9d776a3287.html
