package com.lampnick.archiver;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Archiver {
public void appendArchive(String[] srcFiles, String yarPath) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(yarPath, true);
for (String srcFile : srcFiles) {
addFile(srcFile, fout);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void newArchiveFile(String[] srcFiles, String yarPath) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(yarPath);
for (String srcFile : srcFiles) {
File f = new File(srcFile);
if (f.exists()) {
addFile(srcFile, fout);
} else {
System.out.println("No such a file or directory:" + srcFile);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void addFile(String srcFile, FileOutputStream fout) {
try {
FileInputStream fin = new FileInputStream(srcFile);
// 1.获取文件名并计算文件名的大小
String filename = getFilename(srcFile);
byte[] filenameSize = getFilenameSize(filename);
// 2.1将计算的文件名大小写入第1-4个字节
fout.write(filenameSize);
// 2.2以字节方式存入文件名
fout.write(filename.getBytes());
// 3.计算文件内容大小并将文件内容大小写入到接下来的4个字节
int fileSize = fin.available();
System.out.println(filename + ":" + fileSize);
fout.write(int2Bytes(fileSize));
// 4.将文件内容写入到yar文件
int len = -1;
byte[] b = new byte[1024];
while ((len = fin.read(b)) != -1) {
fout.write(b, 0, len);
}
fin.close();
} catch (Exception e) {
e.printStackTrace();
}
// 4.将文件内容写入
}
/**
* get filename
*
* @param srcFile
* @return
*/
private String getFilename(String srcFile) {
return srcFile.substring(srcFile.lastIndexOf('/'));
}
/**
* get filename's byte size
*
* @param filename
* @return
*/
private byte[] getFilenameSize(String filename) {
int length = filename.length();
System.out.println(filename + "'s name size:" + length);
return int2Bytes(length);
}
/**
* change int to four bytes
*
* @param size
* @return
*/
private byte[] int2Bytes(int size) {
byte[] fnbytes = new byte[4];
fnbytes[0] = (byte) size;// 最低位
fnbytes[1] = (byte) (size >> 8);
fnbytes[2] = (byte) (size >> 16);
fnbytes[3] = (byte) (size >> 24);
for (byte b : fnbytes) {
System.out.print(b + " ");
}
return fnbytes;
}
/**
* unpack a yar file
*
* @param yarPath
* @param unpackPath
*/
public void unArchive(String yarPath, String unpackPath) {
try {
FileInputStream fin = new FileInputStream(yarPath);
// 循环读取下一个文件,并解压到指定目录
int count = 0;
while (readNextFile(fin, unpackPath)) {
count++;
System.out.println("count:" + count);
}
fin.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean readNextFile(FileInputStream fin, String unpackPath) {
try {
int len = -1;
// 1.取出文件名大小
byte[] filenameBytes = new byte[4];
len = fin.read(filenameBytes);
if (len == -1) {
return false;
}
System.out.print("fsize:");
for (byte b : filenameBytes) {
System.out.print(b + " ");
}
System.out.println();
int filenameSize = byteArr2Int(filenameBytes);
System.out.println("filenameSize:" + filenameSize);
// 3.取出文件名
byte[] fname = new byte[filenameSize];
fin.read(fname);
String filename = new String(fname);
FileOutputStream fout = new FileOutputStream(unpackPath + filename);
System.out.println("filename:" + filename);
// 4.取出文件内容大小
byte[] filesizeBytes = new byte[4];
fin.read(filesizeBytes);
double filesize = byteArr2Int(filesizeBytes);
// 5.取出文件内容写到文件
byte[] tmpByte = new byte[1024];
int writeCount = (int) Math.ceil(filesize / 1024);
System.out.println("取文件次数:" + writeCount);
System.out.println("filesize:" + filesize);
int leftSize = (int) filesize;
for (int i = 1; i <= writeCount; i++) {
System.out.println("leftSize:" + leftSize);
if (leftSize >= 1024) {
len = fin.read(tmpByte);
if (len != -1) {
fout.write(tmpByte, 0, len);
}
} else {
byte[] leftByte = new byte[leftSize];
len = fin.read(leftByte);
if (len != -1) {
fout.write(leftByte, 0, len);
}
}
leftSize = (int) filesize - i * 1024;
}
System.out.println("len:" + len);
fout.close();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* four bytes to int
*
* @param bytes
* @return
*/
private int byteArr2Int(byte[] bytes) {
int i0 = (bytes[0] & 0xff);
int i1 = (bytes[1] & 0xff) << 8;
int i2 = (bytes[2] & 0xff) << 16;
int i3 = (bytes[3] & 0xff) << 24;
return i3 | i2 | i1 | i0;
}
}
App.java调用
package com.lampnick.archiver;
import org.junit.Test;
public class App {
/**
11.png:6
11.png:3995
ArrayDemo1.java:15
ArrayDemo1.java:191
Autoloader.php:14
Autoloader.php:1741
ok!
*/
@Test
public void newArchiveTest() {
String[] srcFiles = { "G:/java/archive/11.png",
"G:/java/archive/ArrayDemo1.java",
"G:/java/archive/phpword.php",
"G:/java/archive/测试.c",
"G:/java/archive/Autoloader.php" };
String yarPath = "G:/java/archive/myyar.yar";
Archiver a = new Archiver();
a.newArchiveFile(srcFiles, yarPath);
System.out.println("ok!");
}
@Test
public void appArchiveTest() {
String[] srcFiles = { "G:/java/archive/phpword.php", "G:/java/archive/Autoloader.php" };
String yarPath = "G:/java/archive/myyar.yar";
Archiver a = new Archiver();
a.appendArchive(srcFiles, yarPath);
System.out.println("append ok!");
}
@Test
public void unArchive(){
Archiver a = new Archiver();
String yarPath="G:/java/archive/myyar.yar";
String unpackPath="G:/java/archive/myyar";
a.unArchive(yarPath, unpackPath);
}
private int byteArr2Int(byte[] bytes) {
int i0 = (bytes[0] & 0xff);
int i1 = (bytes[1] & 0xff) << 8;
int i2 = (bytes[2] & 0xff) << 16;
int i3 = (bytes[3] & 0xff) << 24;
return i3 | i2 | i1 | i0;
}
@Test
public void toInt(){
int i = 12;
byte[] b = new byte[4];
// 最低位存最高数字
b[0] = (byte) i;// 最低位
b[1] = (byte) (i >> 8);
b[2] = (byte) (i >> 16);
b[3] = (byte) (i >> 24);
System.out.println(byteArr2Int(b));
}
}
转载请注明:MitNick » java 实现简单的文件归档