import java.io.File;
import java.util.Arrays;
/*
* Used 'Inner Classes' to minimize temptations of JVM exploiting low hanging
* fruits. 'Inner classes' are defined in appendix D of the 'Java Programming
* Language' by Ken Arnold.
* - We moved the class declaration, unchanged, of Hash_Table to within the
* class declaration of Compressor.
* - We moved the class declarations, unchanged, of De_Stack and
Suffix_Table to within the class declaration of Decompressor.
* - pre-computed trivial htab(i) to minimize millions of trivial calls
* - Don McCauley (IBM), Kaivalya 4/16/98
*
* @(#)Compress.java 1.7 06/17/98
* // Don McCauley/kmd - IBM 02/26/98
* // getbyte and getcode fixed -- kaivalya & Don
* compress.c - File compression ala IEEE Computer, June 1984.
*
* Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
* Jim McKie (decvax!mcvax!jim)
* Steve Davies (decvax!vax135!petsd!peora!srd)
* Ken Turkowski (decvax!decwrl!turtlevax!ken)
* James A. Woods (decvax!ihnp4!ames!jaw)
* Joe Orost (decvax!vax135!petsd!joe)
*
* Algorithm from "A Technique for High Performance Data Compression",
* Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
*
* Algorithm:
* Modified Lempel-Ziv method (LZW). Basically finds common
* substrings and replaces them with a variable size code. This is
* deterministic, and can be done on the fly. Thus, the decompression
* procedure needs no input table, but tracks the way the table was built.
*
* This source code is provided as is, without any express or implied warranty.
*/
public class ZCompressUtil {
final static class Compress {
final static int BITS = 16; /* always set to 16 for SPEC95 */
final static int INIT_BITS = 9; /* initial number of bits/code */
final static int HSIZE = 69001; /* 95% occupancy */
final static int SUFFIX_TAB_SZ = 65536; /* 2**BITS */
final static int STACK_SZ = 8000; /* decompression stack size */
final static byte magic_header[] = { (byte) 037, (byte) 0235 }; /* 1F 9D */
/* Defines for third byte of header */
final static int BIT_MASK = 0x1f;
final static int BLOCK_MASK = 0x80;
/*
* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is a
* fourth header byte (for expansion).
*/
/*
* the next two codes should not be changed lightly, as they must not lie
* within the contiguous general code space.
*/
final static int FIRST = 257; /* first free entry */
final static int CLEAR = 256; /* table clear output code */
final static byte lmask[] = { (byte) 0xff, (byte) 0xfe, (byte) 0xfc,
(byte) 0xf8, (byte) 0xf0, (byte) 0xe0, (byte) 0xc0, (byte) 0x80,
(byte) 0x00 };
final static byte rmask[] = { (byte) 0x00, (byte) 0x01, (byte) 0x03,
(byte) 0x07, (byte) 0x0f, (byte) 0x1f, (byte) 0x3f, (byte) 0x7f,
(byte) 0xff };
public static int spec_select_action(byte[] from_buf, int from_count,
int action, byte[] to_buf) {
Input_Buffer in = new Input_Buffer(from_count, from_buf);
Output_Buffer out = new Output_Buffer(to_buf);
if (action == 0) {
Compressor comp = new Compressor(in, out);
comp.compress();
} else {
Decompressor decomp = new Decompressor(in, out);
decomp.decompress();
}
return (out.count());
}
};
/** ************************************************************** */
final static class Input_Buffer {
private int InCnt;
private int Current;
private byte[] InBuff;
public Input_Buffer(int c, byte[] b) {
InCnt = c;
Current = 0;
InBuff = b;
}
// kmd 02/26/98 public byte getbyte() {
public int getbyte() {
if (InCnt > 0) {
InCnt--;
// return( InBuff[Current++] ); // kmd 02/26/98
return (InBuff[Current++] & 0x00FF); // kmd 02/26/98
} else {
// return( (byte)-1 ); // kmd 02/26/98
return (-1); // kmd 02/26/98
}
}
public int readbytes(byte[] buf, int n) {
int i;
if (InCnt <= 0)
return (-1);
if (n > InCnt)
n = InCnt;
for (i = 0; i < n; i++) {
buf[i] = InBuff[Current++];
InCnt--;
}
return (i);
}
};
/** ************************************************************** */
final static class Output_Buffer {
private int OutCnt;
private byte[] OutBuff;
public Output_Buffer(byte[] b) {
OutCnt = 0;
OutBuff = b;
}
public int count() {
return OutCnt;
}
public void putbyte(byte c) {
OutBuff[OutCnt++] = c;
}
public void writebytes(byte[] buf, int n) {
int i;
for (i = 0; i < n; i++)
OutBuff[OutCnt++] = buf[i];
}
};
/** ************************************************************** */
final static class Code_Table {
private short tab[];
public Code_Table() {
tab = new short[Compress.HSIZE];
}
public int of(int i) {
return ((int) tab[i] << 16 >>> 16);
}
public void set(int i, int v) {
tab[i] = (short) v;
}
public void clear(int size) {
int code;
for (code = 0; code < size; code++) {
tab[code] = 0;
}
}
};
/** ************************************************************** */
static class Comp_Base {
protected int n_bits; /* number of bits/code */
protected int maxbits; /* user settable max # bits/code */
protected int maxcode; /* maximum code, given n_bits */
protected int maxmaxcode; /* should NEVER generate this code */
protected int offset;
protected int block_compress;
protected int free_ent; /* first unused entry */
protected int clear_flg;
protected Input_Buffer Input;
protected Output_Buffer Output;
protected byte buf[];
public Comp_Base(Input_Buffer in, Output_Buffer out) {
Input = in;
Output = out;
maxbits = Compress.BITS;
block_compress = Compress.BLOCK_MASK;
buf = new byte[Compress.BITS];
}
public int MAXCODE() {
return ((1 << (n_bits)) - 1);
}
};
/** ************************************************************** */
/*
* compress (Originally: stdin to stdout -- Changed by SPEC to: memory to
* memory)
*
* Algorithm: use open addressing double hashing (no chaining) on the prefix
* code / next character combination. We do a variant of Knuth's algorithm D
* (vol. 3, sec. 6.4) along with G. Knott's relatively-prime secondary probe.
* Here, the modular division first probe is gives way to a faster exclusive-or
* manipulation. Also do block compression with an adaptive reset, whereby the
* code table is cleared when the compression ratio decreases, but after the
* table fills. The variable-length output codes are re-sized at this point, and
* a special CLEAR code is generated for the decompressor. Late addition:
* construct the table according to file size for noticeable speed improvement
* on small files. Please direct questions about this implementation to
* ames!jaw.
*/
final static class Compressor extends Comp_Base {
private final static int CHECK_GAP = 10000; /* ratio check interval */
private int ratio;
private int checkpoint;
private int in_count; /* length of input */
private int out_count; /* # of codes output */
private int bytes_out; /* length of compressed output */
private Hash_Table htab;
private Code_Table codetab;
public Compressor(Input_Buffer in, Output_Buffer out) {
super(in, out);
if (maxbits < Compress.INIT_BITS)
maxbits = Compress.INIT_BITS;
if (maxbits > Compress.BITS)
maxbits = Compress.BITS;
maxmaxcode = 1 << maxbits;
n_bits = Compress.INIT_BITS;
maxcode = MAXCODE();
offset = 0;
bytes_out = 3; /* includes 3-byte header mojo */
out_count = 0;
clear_flg = 0;
ratio = 0;
in_count = 1;
checkpoint = CHECK_GAP;
free_ent = ((block_compress != 0) ? Compress.FIRST : 256);
htab = new Hash_Table(); // dm/kmd 4/10/98
codetab = new Code_Table();
Output.putbyte(Compress.magic_header[0]);
Output.putbyte(Compress.magic_header[1]);
Output.putbyte((byte) (maxbits | block_compress));
}
public void compress() {
int fcode;
int i = 0;
int c;
int ent;
int disp;
int hsize_reg;
int hshift;
ent = Input.getbyte();
hshift = 0;
for (fcode = htab.hsize(); fcode < 65536; fcode *= 2)
hshift++;
hshift = 8 - hshift; /* set hash code range bound */
hsize_reg = htab.hsize();
htab.clear(); /* clear hash table */
next_byte: while ((c = Input.getbyte()) != -1) {
in_count++;
fcode = (((int) c << maxbits) + ent);
i = ((c << hshift) ^ ent); /* xor hashing */
int temphtab = htab.of(i); // dm/kmd 4/15
// dm kmd if ( htab.of (i) == fcode ) { // dm/kmd 4/15
if (temphtab == fcode) {
ent = codetab.of(i);
continue next_byte;
}
// dm kmd 4/15 if ( htab.of (i) >= 0 ) { /* non-empty slot */
if (temphtab >= 0) { /* non-empty slot dm kmd 4/15 */
disp = hsize_reg - i; /* secondary hash (after G. Knott) */
if (i == 0)
disp = 1;
do {
if ((i -= disp) < 0)
i += hsize_reg;
temphtab = htab.of(i); // dm/kmd 4/15
// dm/kmd 4/15 if ( htab.of (i) == fcode ) {
if (temphtab == fcode) {
ent = codetab.of(i);
continue next_byte;
}
// dm/kmd 4/15 } while ( htab.of (i) > 0 );
} while (temphtab > 0); // dm kmd 4/15
}
output(ent);
out_count++;
ent = c;
if (free_ent < maxmaxcode) {
codetab.set(i, free_ent++); /* code -> hashtable */
htab.set(i, fcode);
} else if ((in_count >= checkpoint) && (block_compress != 0))
cl_block();
}
/*
* Put out the final code.
*/
output(ent);
out_count++;
output(-1);
return;
}
/*
* Output the given code. Inputs: code: A n_bits-bit integer. If == -1, then
* EOF. This assumes that n_bits =< (long)wordsize - 1. Outputs: Outputs
* code to the file. Assumptions: Chars are 8 bits long. Algorithm: Maintain
* a BITS character long buffer (so that 8 codes will fit in it exactly).
*/
private void output(int code) {
int r_off = offset, bits = n_bits;
int bp = 0;
if (code >= 0) {
/*
* Get to the first byte.
*/
bp += (r_off >> 3);
r_off &= 7;
/*
* Since code is always >= 8 bits, only need to mask the first hunk
* on the left.
*/
buf[bp] = (byte) ((buf[bp] & Compress.rmask[r_off]) | (code << r_off)
& Compress.lmask[r_off]);
bp++;
bits -= (8 - r_off);
code >>= 8 - r_off;
/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
if (bits >= 8) {
buf[bp++] = (byte) code;
code >>= 8;
bits -= 8;
}
/* Last bits. */
if (bits != 0)
buf[bp] = (byte) code;
offset += n_bits;
if (offset == (n_bits << 3)) {
bp = 0;
bits = n_bits;
bytes_out += bits;
do
Output.putbyte(buf[bp++]);
while (--bits != 0);
offset = 0;
}
/*
* If the next entry is going to be too big for the code size, then
* increase it, if possible.
*/
if (free_ent > maxcode || (clear_flg > 0)) {
/*
* Write the whole buffer, because the input side won't discover
* the size increase until after it has read it.
*/
if (offset > 0) {
Output.writebytes(buf, n_bits);
bytes_out += n_bits;
}
offset = 0;
if (clear_flg != 0) {
n_bits = Compress.INIT_BITS;
maxcode = MAXCODE();
clear_flg = 0;
} else {
n_bits++;
if (n_bits == maxbits)
maxcode = maxmaxcode;
else
maxcode = MAXCODE();
}
}
} else {
/*
* At EOF, write the rest of the buffer.
*/
if (offset > 0)
Output.writebytes(buf, ((offset + 7) / 8));
bytes_out += (offset + 7) / 8;
offset = 0;
}
}
/* table clear for block compress */
private void cl_block() {
int rat;
checkpoint = in_count + CHECK_GAP;
if (in_count > 0x007fffff) { /* shift will overflow */
rat = bytes_out >> 8;
if (rat == 0) { /* Don't divide by zero */
rat = 0x7fffffff;
} else {
rat = in_count / rat;
}
} else {
rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
}
if (rat > ratio) {
ratio = rat;
} else {
ratio = 0;
htab.clear();
free_ent = Compress.FIRST;
clear_flg = 1;
output((int) Compress.CLEAR);
}
}
final class Hash_Table { // moved 4/15/98 dm/kmd
/*
* Use protected instead of private to allow access by parent class of
* inner class. wnb 4/17/98
*/
protected int tab[]; // for dynamic table sizing */
protected int size;
public Hash_Table() {
size = Compress.HSIZE;
tab = new int[size];
}
public int of(int i) {
return tab[i];
}
public void set(int i, int v) {
tab[i] = v;
}
public int hsize() {
return size;
}
public void clear() {
int i;
for (i = 0; i < size; i++) {
tab[i] = -1;
}
}
};
};
/** ************************************************************** */
/*
* Decompress stdin to stdout. This routine adapts to the codes in the file
* building the "string" table on-the-fly; requiring no table to be stored in
* the compressed file. The tables used herein are shared with those of the
* compress() routine. See the definitions above.
*/
final static class Decompressor extends Comp_Base {
private int size;
private Code_Table tab_prefix;
private Suffix_Table tab_suffix;
private De_Stack de_stack;
public Decompressor(Input_Buffer in, Output_Buffer out) {
super(in, out);
/* Check the magic number */
if (((Input.getbyte() & 0xFF) != (Compress.magic_header[0] & 0xFF))
|| ((Input.getbyte() & 0xFF) != (Compress.magic_header[1] & 0xFF))) {
System.err.println("stdin: not in compressed format");
// System.exit(1);
}
maxbits = Input.getbyte(); /* set -b from file */
block_compress = maxbits & Compress.BLOCK_MASK;
maxbits &= Compress.BIT_MASK;
maxmaxcode = 1 << maxbits;
if (maxbits > Compress.BITS) {
System.err.println("stdin: compressed with " + maxbits
+ " bits, can only handle " + Compress.BITS + " bits");
// System.exit(1);
}
n_bits = Compress.INIT_BITS;
maxcode = MAXCODE();
offset = 0;
size = 0;
clear_flg = 0;
free_ent = ((block_compress != 0) ? Compress.FIRST : 256);
tab_prefix = new Code_Table();
tab_suffix = new Suffix_Table();
de_stack = new De_Stack();
/*
* As above, initialize the first 256 entries in the table.
*/
tab_prefix.clear(256);
tab_suffix.init(256);
}
public void decompress() {
int finchar;
int code, oldcode, incode;
finchar = oldcode = getcode();
if (oldcode == -1) /* EOF already? */
return; /* Get out of here */
Output.putbyte((byte) finchar); /* first code must be 8 bits = byte */
while ((code = getcode()) > -1) {
if ((code == Compress.CLEAR) && (block_compress != 0)) {
tab_prefix.clear(256);
clear_flg = 1;
free_ent = Compress.FIRST - 1;
if ((code = getcode()) == -1) /* O, untimely death! */
break;
}
incode = code;
/*
* Special case for KwKwK string.
*/
if (code >= free_ent) {
de_stack.push((byte) finchar);
code = oldcode;
}
/*
* Generate output characters in reverse order
*/
while (code >= 256) {
de_stack.push(tab_suffix.of(code));
code = tab_prefix.of(code);
}
de_stack.push((byte) (finchar = tab_suffix.of(code)));
/*
* And put them out in forward order
*/
do
Output.putbyte(de_stack.pop());
while (!de_stack.is_empty());
/*
* Generate the new entry.
*/
if ((code = free_ent) < maxmaxcode) {
tab_prefix.set(code, oldcode);
tab_suffix.set(code, (byte) finchar);
free_ent = code + 1;
}
/*
* Remember previous code.
*/
oldcode = incode;
}
}
/*
* Read one code from the standard input. If EOF, return -1. Inputs: stdin
* Outputs: code or -1 is returned.
*/
private int getcode() {
int code;
int r_off, bits;
int bp = 0;
if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
/*
* If the next entry will be too big for the current code size, then
* we must increase the size. This implies reading a new buffer
* full, too.
*/
if (free_ent > maxcode) {
n_bits++;
if (n_bits == maxbits)
maxcode = maxmaxcode; /* won't get any bigger now */
else
maxcode = MAXCODE();
}
if (clear_flg > 0) {
n_bits = Compress.INIT_BITS;
maxcode = MAXCODE();
clear_flg = 0;
}
size = Input.readbytes(buf, n_bits);
if (size <= 0)
return -1; /* end of file */
offset = 0;
/* Round size down to integral number of codes */
size = (size << 3) - (n_bits - 1);
}
r_off = offset;
bits = n_bits;
/*
* Get to the first byte.
*/
bp += (r_off >> 3);
r_off &= 7;
/* Get first part (low order bits) */
code = ((buf[bp++] >> r_off) & Compress.rmask[8 - r_off]) & 0xff;
bits -= (8 - r_off);
r_off = 8 - r_off; /* now, offset into code word */
/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
if (bits >= 8) {
code |= (buf[bp++] & 0xff) << r_off;
r_off += 8;
bits -= 8;
}
/* high order bits. */
// code |= (buf[bp] & Compress.rmask[bits]) << r_off; // kmd
// Don McCauley/kmd - IBM 02/26/98
if (bits > 0)
code |= (buf[bp] & Compress.rmask[bits]) << r_off;
offset += n_bits;
return code;
}
/** ************************************************************** */
final class De_Stack { // moved 4/15/98 dm/kmd
/*
* Use protected instead of private to allow access by parent class of
* inner class. wnb 4/17/98
*/
protected byte tab[];
protected int index;
public De_Stack() {
tab = new byte[Compress.STACK_SZ];
index = 0;
}
public void push(byte c) {
tab[index++] = c;
}
public byte pop() {
index--;
return tab[index];
}
public boolean is_empty() {
return (index == 0);
}
};
/** ************************************************************** */
final class Suffix_Table { // moved 4/15/98 dm/kmd
/*
* Use protected instead of private to allow access by parent class of
* inner class. wnb 4/17/98
*/
protected byte tab[];
public Suffix_Table() {
tab = new byte[Compress.SUFFIX_TAB_SZ];
}
public byte of(int i) {
return tab[i];
}
public void set(int i, byte v) {
tab[i] = v;
}
public void init(int size) {
int code;
for (code = 0; code < size; code++) {
tab[code] = (byte) code;
}
}
};
};
/**
* 生成.tar.Z文件
*/
public static void compresstTarZFile(File srcFile,File tarZFile) throws Exception {
TarUtils.archive(srcFile,tarZFile);
byte[] tarByte =ByteUtil.getBytes(tarZFile.getAbsolutePath());
byte[] tarZByte = new byte[tarByte.length];
int len = Compress.spec_select_action(tarByte,tarByte.length,0,tarZByte);
tarZByte = Arrays.copyOf(tarZByte,len);
ByteUtil.saveFile(tarZByte,tarZFile);
}
}
TarUtils
/**
* 2010-4-20
*/
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import java.io.*;
/**
* TAR工具
*
* @author
* @since 1.0
*/
public abstract class TarUtils {
private static final String BASE_DIR = "";
// 符号"/"用来作为目录标识判断符
private static final String PATH = "/";
private static final int BUFFER = 1024;
private static final String EXT = ".tar";
/**
* 归档
*
* @param srcPath
* @param destPath
* @throws Exception
*/
public static void archive(String srcPath, String destPath)
throws Exception {
File srcFile = new File(srcPath);
archive(srcFile, destPath);
}
/**
* 归档
*
* @param srcFile
* 源路径
* @param destFile
* 目标路径
* @throws Exception
*/
public static void archive(File srcFile, File destFile) throws Exception {
TarArchiveOutputStream taos = new TarArchiveOutputStream(
new FileOutputStream(destFile));
archive(srcFile, taos, BASE_DIR);
taos.flush();
taos.close();
}
/**
* 归档
*
* @param srcFile
* @throws Exception
*/
public static void archive(File srcFile) throws Exception {
String name = srcFile.getName();
//String basePath = srcFile.getParent();
String destPath = name + EXT;
archive(srcFile, destPath);
}
/**
* 归档文件
*
* @param srcFile
* @param destPath
* @throws Exception
*/
public static void archive(File srcFile, String destPath) throws Exception {
archive(srcFile, new File(destPath));
}
/**
* 归档
*
* @param srcPath
* @throws Exception
*/
public static void archive(String srcPath) throws Exception {
File srcFile = new File(srcPath);
archive(srcFile);
}
/**
* 归档
*
* @param srcFile
* 源路径
* @param taos
* TarArchiveOutputStream
* @param basePath
* 归档包内相对路径
* @throws Exception
*/
private static void archive(File srcFile, TarArchiveOutputStream taos,
String basePath) throws Exception {
if (srcFile.isDirectory()) {
archiveDir(srcFile, taos, basePath);
} else {
archiveFile(srcFile, taos, basePath);
}
}
/**
* 目录归档
*
* @param dir
* @param taos
* TarArchiveOutputStream
* @param basePath
* @throws Exception
*/
private static void archiveDir(File dir, TarArchiveOutputStream taos,
String basePath) throws Exception {
File[] files = dir.listFiles();
if (files.length < 1) {
TarArchiveEntry entry = new TarArchiveEntry(basePath
+ dir.getName() + PATH);
taos.putArchiveEntry(entry);
taos.closeArchiveEntry();
}
for (File file : files) {
// 递归归档
archive(file, taos, basePath + dir.getName() + PATH);
}
}
/**
* 数据归档
*
* @param taos
* 待归档数据
* @param dir
* 归档数据的当前路径
* @param file
* 归档文件名
* @param taos
* TarArchiveOutputStream
* @throws Exception
*/
private static void archiveFile(File file, TarArchiveOutputStream taos,
String dir) throws Exception {
/**
* 归档内文件名定义
*
* <pre>
* 如果有多级目录,那么这里就需要给出包含目录的文件名
* 如果用WinRAR打开归档包,中文名将显示为乱码
* </pre>
*/
TarArchiveEntry entry = new TarArchiveEntry(dir + file.getName());
entry.setSize(file.length());
taos.putArchiveEntry(entry);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
file));
int count;
byte data[] = new byte[BUFFER];
while ((count = bis.read(data, 0, BUFFER)) != -1) {
taos.write(data, 0, count);
}
bis.close();
taos.closeArchiveEntry();
}
/**
* 解归档
*
* @param srcFile
* @throws Exception
*/
public static void dearchive(File srcFile) throws Exception {
String basePath = srcFile.getParent();
dearchive(srcFile, basePath);
}
/**
* 解归档
*
* @param srcFile
* @param destFile
* @throws Exception
*/
public static void dearchive(File srcFile, File destFile) throws Exception {
TarArchiveInputStream tais = new TarArchiveInputStream(
new FileInputStream(srcFile));
dearchive(destFile, tais);
tais.close();
}
/**
* 解归档
*
* @param srcFile
* @param destPath
* @throws Exception
*/
public static void dearchive(File srcFile, String destPath)
throws Exception {
dearchive(srcFile, new File(destPath));
}
/**
* 文件 解归档
*
* @param destFile
* 目标文件
* @param tais
* ZipInputStream
* @throws Exception
*/
private static void dearchive(File destFile, TarArchiveInputStream tais)
throws Exception {
TarArchiveEntry entry = null;
while ((entry = tais.getNextTarEntry()) != null) {
// 文件
String dir = destFile.getPath() + File.separator + entry.getName();
File dirFile = new File(dir);
// 文件检查
fileProber(dirFile);
if (entry.isDirectory()) {
dirFile.mkdirs();
} else {
dearchiveFile(dirFile, tais);
}
}
}
/**
* 文件 解归档
*
* @param srcPath
* 源文件路径
*
* @throws Exception
*/
public static void dearchive(String srcPath) throws Exception {
File srcFile = new File(srcPath);
dearchive(srcFile);
}
/**
* 文件 解归档
*
* @param srcPath
* 源文件路径
* @param destPath
* 目标文件路径
* @throws Exception
*/
public static void dearchive(String srcPath, String destPath)
throws Exception {
File srcFile = new File(srcPath);
dearchive(srcFile, destPath);
}
/**
* 文件解归档
*
* @param destFile
* 目标文件
* @param tais
* TarArchiveInputStream
* @throws Exception
*/
private static void dearchiveFile(File destFile, TarArchiveInputStream tais)
throws Exception {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
int count;
byte data[] = new byte[BUFFER];
while ((count = tais.read(data, 0, BUFFER)) != -1) {
bos.write(data, 0, count);
}
bos.close();
}
/**
* 文件探针
*
* <pre>
* 当父目录不存在时,创建目录!
* </pre>
*
* @param dirFile
*/
private static void fileProber(File dirFile) {
File parentFile = dirFile.getParentFile();
if (!parentFile.exists()) {
// 递归寻找上级目录
fileProber(parentFile);
parentFile.mkdir();
}
}
/**
*
* @param file 压缩的文件路径
* @param srcFile 需要压缩的文件
* @throws Exception
*/
public static void tarFile(File file, File srcFile) throws Exception {
TarArchiveOutputStream taos = new TarArchiveOutputStream(new FileOutputStream(srcFile));
TarArchiveEntry tae = new TarArchiveEntry(file);
tae.setSize(file.length());//大小
tae.setName(new String(file.getName().getBytes("gbk"), "ISO-8859-1"));//不设置会默认全路径
taos.putArchiveEntry(tae);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int count;
byte data[] = new byte[1024];
while ((count = bis.read(data, 0, 1024)) != -1) {
taos.write(data, 0, count);
}
bis.close();
taos.closeArchiveEntry();
}
public static void archiveTarFile(String destPath, File srcFile) throws Exception {
TarArchiveInputStream tais = new TarArchiveInputStream(new FileInputStream(srcFile));
TarArchiveEntry tae = null;
while ((tae = tais.getNextTarEntry()) != null) {
String dir = destPath + File.separator + tae.getName();//tar档中文件
File dirFile = new File(dir);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dirFile));
int count;
byte data[] = new byte[1024];
while ((count = tais.read(data, 0, 1024)) != -1) {
bos.write(data, 0, count);
}
bos.close();
}
tais.close();
}
/**
* 解压tar.gz文件
* tar文件只是把多个文件或文件夹打包合成一个文件,本身并没有进行压缩。gz是进行过压缩的文件。
* @param dir
* @param
* @throws Exception
*/
public static void deGzipArchive(String desDir, File srcGZFile)
throws Exception {
InputStream is = null;
CompressorInputStream in = null;
TarArchiveInputStream tin = null;
try {
is = new FileInputStream(srcGZFile);
in = new GzipCompressorInputStream(is, true);
tin = new TarArchiveInputStream(in);
dearchive(new File(desDir),tin);
}finally {
if (in!=null){
in.close();
}
if (tin!=null){
tin.close();
}
}
}
}
ByteUtil
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
/**
* byte数组工具类实现byte[]与文件之间的相互转换
*
* @Date 2018-03-26
*/
public class ByteUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ByteUtil.class);
/**
* 获得指定文件的byte数组
*/
public static byte[] getBytes(String filePath) throws Exception{
byte[] buffer = null;
try {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} catch (FileNotFoundException e) {
LOGGER.error("文件未找到",e);
throw e;
} catch (IOException e) {
LOGGER.error("io异常",e);
throw e;
}
return buffer;
}
/**
* 根据byte数组,生成文件
*/
public static void saveFile(byte[] bfile, String filePath,String fileName) throws Exception{
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(filePath);
//判断文件目录是否存在
if(!dir.exists()&&dir.isDirectory()){
dir.mkdirs();
}
file = new File(filePath+fileName);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} catch (Exception e) {
LOGGER.error("io异常",e);
throw e;
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e1) {
LOGGER.error("io异常",e1);
throw e1;
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
LOGGER.error("io异常",e1);
throw e1;
}
}
}
}
/**
* 根据byte数组,生成文件
*/
public static void saveFile(byte[] bfile, File file) throws Exception{
BufferedOutputStream bos = null;
FileOutputStream fos = null;
try {
//判断文件是否存在
if(!file.exists()){
file.createNewFile();
}
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} catch (Exception e) {
LOGGER.error("io异常",e);
throw e;
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e1) {
LOGGER.error("io异常",e1);
throw e1;
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
LOGGER.error("io异常",e1);
throw e1;
}
}
}
}
}