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 实现简单的文件归档