今日工作中有要求需要对.Tar类型文件进行压缩和解压处理。按照常规处理之后出现了压缩文件乱码,以及压缩文件不能对之进行正常解压的现象。经过一番调整,发现问题在与文件解压与压缩时的编码设置。以下代码基于ant-1.9.2.jar
解压
/**
* 解压tar文件。tar文件中,文件名都是ascii编码,必须中文必须转换为gbk编码。
*
* @param file
* @param outputDir
*/
public static void unTar(File file, String outputDir) {
TarInputStream tarIn = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
tarIn = new TarInputStream(fileInputStream);
createDirectory(outputDir, null);// 创建输出目录
TarEntry entry = null;
while ((entry = tarIn.getNextEntry()) != null && !"".equals(entry.getName())) {
if (entry.isDirectory()) {// 是目录
createDirectory(outputDir, entry.getName());// 创建空目录
} else {// 是文件
byte[] tmp = new byte[entry.getName().length()];
for (int i = 0; i < entry.getName().length(); i++) {
char c = entry.getName().charAt(i);
byte b = (byte) (0xFF & c);
tmp[i] = b;
}
String fName = new String(tmp, "GBK");
File tmpFile = new File(outputDir + "/" + fName);
createDirectory(tmpFile.getParent() + "/", null);// 创建输出目录
OutputStream out = new FileOutputStream(tmpFile);
tarIn.copyEntryContents(out);
closeQuietly(out);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
closeQuietly(fileInputStream);
closeQuietly(tarIn);
}
}
压缩
/**
*
* @param targetFileName
* @return
*/
private static TarOutputStream getTarOutputStream(String targetFileName) {
FileOutputStream fileOutputStream = null;
File path = new File(targetFileName).getParentFile();
if (!path.exists()) {
path.mkdirs();
}
try {
fileOutputStream = new FileOutputStream(targetFileName);
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
}
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
TarOutputStream out = new TarOutputStream(bufferedOutputStream);
out.setLongFileMode(TarOutputStream.LONGFILE_GNU);// 如果不加下面这段,当压缩包中的路径字节数超过100 byte时,就会报错
return out;
}
/**
*
* @param inputFile 待打包文件/文件夹
* @param targetFileName
*/
public static void pack(File inputFile, String targetFileName) {
TarOutputStream out = getTarOutputStream(targetFileName);
tarPack(out, inputFile, inputFile.getName());
try {
if (null != out) {
out.close();
}
} catch (IOException e) {
logger.error(e == null ? "" : e.getMessage(), e);
}
}
/**
*
* @param out
* @param inputFile 打包后生成文件的流 inputFile
* @param base 要压缩的文件夹或文件 base 打包文件中的路径
*/
private static void tarPack(TarOutputStream out, File inputFile, String base) {
if (inputFile.isDirectory()) // 打包文件夹
{
packFolder(out, inputFile, base);
} else // 打包文件
{
packFile(out, inputFile, base);
}
}
/**
*
* @param out
* @param inputFile
* @param base
*/
private static void packFolder(TarOutputStream out, File inputFile, String base) {
File[] fileList = inputFile.listFiles();
try {
out.putNextEntry(new org.apache.tools.tar.TarEntry(base + "/"));// 在打包文件中添加路径
} catch (IOException e) {
System.err.println(e.getMessage());
}
base = base.length() == 0 ? "" : base + "/";
for (File file : fileList) {
tarPack(out, file, base + file.getName());//回调
}
}
/**
*
* @param out
* @param inputFile
* @param base
*/
private static void packFile(TarOutputStream out, File inputFile, String base) {
TarEntry tarEntry = null;
try {
tarEntry = new TarEntry(new String(base.getBytes("GBK"), "ISO-8859-1"));//getBytes必须设置编码,否则会导致编码错误;
} catch (UnsupportedEncodingException e1) {
System.err.println(e1.getMessage());
}
tarEntry.setSize(inputFile.length());// 设置打包文件的大小,如果不设置,打包有内容的文件时,会报错
try {
out.putNextEntry(tarEntry);
} catch (IOException e) {
System.err.println(e.getMessage());
}
try {
byte[] wBuf = FileUtils.readFileToByteArray(inputFile);
out.write(wBuf);
} catch (IOException e) {
System.err.println(e.getMessage());
} catch (NullPointerException e) {
System.err.println(e.getMessage());
} finally {
try {
if (null != out) {
out.closeEntry();
}
} catch (IOException e) {
}
}
}