import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarOutputStream;
import org.apache.tools.zip.ZipOutputStream;
/*
* 功能:壓縮文件成tar.gz格式
*/
public class TarUtils {
private static int BUFFER = 1024 * 4; // 緩衝大小
private static byte[] B_ARRAY = new byte[BUFFER];
/*
* 方法功能:打包單個文件或文件夾 參數:inputFileName 要打包的文件夾或文件的路徑 targetFileName 打包後的文件路徑
*/
public void execute(String inputFileName, String targetFileName) {
File inputFile = new File(inputFileName);
String base = inputFileName
.substring(inputFileName.lastIndexOf("/") + 1);
TarOutputStream out = getTarOutputStream(targetFileName);
tarPack(out, inputFile, base);
try {
if (null != out) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
compress(new File(targetFileName));
}
/*
* 方法功能:打包多個文件或文件夾 參數:inputFileNameList 要打包的文件夾或文件的路徑的列表 targetFileName
* 打包後的文件路徑
*/
public void execute(List<String> inputFileNameList, String targetFileName) {
TarOutputStream out = getTarOutputStream(targetFileName);
for (String inputFileName : inputFileNameList) {
File inputFile = new File(inputFileName);
String base = inputFileName.substring(inputFileName
.lastIndexOf("/") + 1);
tarPack(out, inputFile, base);
}
try {
if (null != out) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
compress(new File(targetFileName));
}
/*
* 方法功能:打包成tar文件 參數:out 打包後生成文件的流 inputFile 要壓縮的文件夾或文件 base 打包文件中的路徑
*/
private void tarPack(TarOutputStream out, File inputFile, String base) {
if (inputFile.isDirectory()) // 打包文件夾
{
packFolder(out, inputFile, base);
} else // 打包文件
{
packFile(out, inputFile, base);
}
}
/*
* 方法功能:遍歷文件夾下的內容,如果有子文件夾,就調用tarPack方法 參數:out 打包後生成文件的流 inputFile 要壓縮的文件夾或文件
* base 打包文件中的路徑
*/
private void packFolder(TarOutputStream out, File inputFile, String base) {
File[] fileList = inputFile.listFiles();
try {
// 在打包文件中添加路徑
out.putNextEntry(new TarEntry(base + "/"));
} catch (IOException e) {
e.printStackTrace();
}
base = base.length() == 0 ? "" : base + "/";
for (File file : fileList) {
tarPack(out, file, base + file.getName());
}
}
/*
* 方法功能:打包文件 參數:out 壓縮後生成文件的流 inputFile 要壓縮的文件夾或文件 base 打包文件中的路徑
*/
private void packFile(TarOutputStream out, File inputFile, String base) {
TarEntry tarEntry = new TarEntry(base);
// 設置打包文件的大小,如果不設置,打包有內容的文件時,會報錯
tarEntry.setSize(inputFile.length());
try {
out.putNextEntry(tarEntry);
} catch (IOException e) {
e.printStackTrace();
}
FileInputStream in = null;
try {
in = new FileInputStream(inputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int b = 0;
try {
while ((b = in.read(B_ARRAY, 0, BUFFER)) != -1) {
out.write(B_ARRAY, 0, b);
}
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
System.err
.println("NullPointerException info ======= [FileInputStream is null]");
} finally {
try {
if (null != in) {
in.close();
}
if (null != out) {
out.closeEntry();
}
} catch (IOException e) {
}
}
}
/*
* 方法功能:把打包的tar文件壓縮成gz格式 參數:srcFile 要壓縮的tar文件路徑
*/
private void compress(File srcFile) {
File target = new File(srcFile.getAbsolutePath() + ".gz");
FileInputStream in = null;
GZIPOutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new GZIPOutputStream(new FileOutputStream(target));
int number = 0;
while ((number = in.read(B_ARRAY, 0, BUFFER)) != -1) {
out.write(B_ARRAY, 0, number);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* 方法功能:獲得打包後文件的流 參數:targetFileName 打包後文件的路徑
*/
private TarOutputStream getTarOutputStream(String targetFileName) {
// 如果打包文件沒有.tar後綴名,就自動加上
targetFileName = targetFileName.endsWith(".tar") ? targetFileName
: targetFileName + ".tar";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(targetFileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
fileOutputStream);
TarOutputStream out = new TarOutputStream(bufferedOutputStream);
// 如果不加下面這段,當壓縮包中的路徑字節數超過100 byte時,就會報錯
out.setLongFileMode(TarOutputStream.LONGFILE_GNU);
return out;
}
}