将各种类型的文件统一放入.yar 文件下
归档:将文件的属性(文件类型和文件的长度)定制成文件头存放在归档文件中的文件内容前。
解归档:根据归档的规则将文件解读成一个个独立的文件
package cn.yif.Archiver; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; public class Archiver { /** * 创建归档文件 */ public void newArchiveFile(String[] srcPaths, String yarPath){ FileOutputStream fout = null; try { //创建yar归档文件的输出流 fout = new FileOutputStream(yarPath); for (String srcPath : srcPaths){ //向yar归档文件中添加文件 addFile(srcPath, fout); } }catch (Exception e){ e.printStackTrace(); }finally { if (fout != null) { try { fout.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 向yar归档文件中添加文件 * @param srcPath * @param fout */ private void addFile(String srcPath, FileOutputStream fout) { FileInputStream fin = null; try { // 1、取出srcPath文件类型和长度 int fType = getFileType(srcPath); // 2、取出文件的长度 fin = new FileInputStream(srcPath); int length = fin.available(); // 3、将ftype写入fout byte bFtype = (byte) fType; fout.write(new byte[]{bFtype}); //4、将长度写入yar中 byte[] bytes = int2ByteArr(length); fout.write(bytes); //5、写入文件内容 int len = -1; byte[] buffer = new byte[1024]; while ((len = fin.read(buffer)) != -1){ fout.write(buffer, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fin.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 将整数转换成字节数组 * @param i * @return */ public static byte[] int2ByteArr(int i) { byte[] bytes = new byte[4]; bytes[0] = (byte) (i & 0xff); bytes[1] = (byte) ((i >> 8) & 0xff); bytes[2] = (byte) ((i >> 16) & 0xff); bytes[3] = (byte) ((i >> 24) & 0xff); return bytes; } public static void main(String[] args) { System.out.println(Arrays.toString(int2ByteArr(800))); } /** * * @param srcPath * @return */ private int getFileType(String srcPath) { //得到文件扩展名 String ext = srcPath.substring(srcPath.lastIndexOf(".")).toLowerCase(); int type = -1; if (".txt".equals(ext)){ type = 0; }else if (".jpg".equals(ext)){ type = 1; }else if (".avi".equals(ext)){ type = 2; }else if (".gif".equals(ext)){ type = 3; }else if (".exe".equals(ext)){ type = 4; } return type; } /** * 向归档文件中添加新文件 */ public void appendFile(String srcPath, String yarPath){ FileOutputStream fos = null; try { fos = new FileOutputStream(yarPath, true); addFile(srcPath, fos); } catch (FileNotFoundException e) { e.printStackTrace(); }finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 解归档文件 */ public void unarchive(String yarPath, String destDir){ FileInputStream fin = null; try { fin = new FileInputStream(yarPath); int i = 1; //循环读取下一个文件 while (readNextFile(destDir, Integer.toString(i),fin)){ i++; } }catch (Exception e){ e.printStackTrace(); } } /** * 读取下一个文件 */ private boolean readNextFile(String destDir, String fileName, FileInputStream fin) { int type = 0; FileOutputStream fout = null; try { //文件类型 type = fin.read(); String ext = getFileExt(type); if (type == -1){ return false; } //0、构造文件 fout = new FileOutputStream(destDir + "\\" + fileName + ext); //1、读取文件长度 byte[] length = new byte[4]; fin.read(length); //2、转换字节数组成int int fileLength = byteArr2Int(length); //3、读取文件 写入新文件 byte[] buffer = new byte[1024]; //计算读取文件的循环次数 int count = 0; if (fileLength % buffer.length == 0){ count = fileLength / buffer.length; }else{ count = fileLength / buffer.length + 1; } //开始循环读取 for (int i = 0; i < count; i++) { //不是最后一次 if (i != count -1){ fin.read(buffer); fout.write(buffer); }else{ byte[] buf0 = new byte[fileLength % buffer.length]; fin.read(buf0); fout.write(buf0); } } } catch (IOException e) { e.printStackTrace(); }finally { try { if (fout != null){ fout.close(); } } catch (IOException e) { e.printStackTrace(); } } return true; } /** * 通过文件类型得到扩展名 * @param type * @return */ private String getFileExt(int type) { if (type == 0) return ".txt"; else if (type == 1) return ".jpg"; else if (type == 2) return ".avi"; else if (type == 3) return ".gif"; else if (type == 4) return ".exe"; else return ".tmp"; } /** * 将byte数组转换成int * @param * @return */ private int byteArr2Int(byte[] bytes) { return (bytes[3] & 0xff) << 24 | (bytes[2] & 0xff) << 16 | (bytes[1] & 0xff) << 8 | (bytes[0] & 0xff); } }
调用方法
package cn.yif.Archiver; import org.junit.jupiter.api.Test; public class App { public static void main(String[] args) { Archiver archiver = new Archiver(); String[] srcPaths = { "D:\\others\\arch\\a.jpg", "D:\\others\\arch\\b.jpg", "D:\\others\\arch\\hi.txt" }; String yarPath = "d:\\others\\arch\\myyar.yar"; archiver.newArchiveFile(srcPaths, yarPath); System.out.println("over!!!"); } /** * 向归档文件中添加新文件 */ @Test public void addFile(){ Archiver archiver = new Archiver(); archiver.appendFile("D:\\others\\arch\\hi.txt","d:\\others\\arch\\myyar.yar" ); System.out.println("over"); } @Test public void unarchiveFile(){ Archiver archiver = new Archiver(); archiver.unarchive("d:\\others\\arch\\myyar.yar","d:\\others\\arch\\unarch\\" ); System.out.println("over"); } }
package cn.yif.Archiver; import org.junit.jupiter.api.Test; public class App { public static void main(String[] args) { Archiver archiver = new Archiver(); String[] srcPaths = { "D:\\others\\arch\\a.jpg", "D:\\others\\arch\\b.jpg", "D:\\others\\arch\\hi.txt" }; String yarPath = "d:\\others\\arch\\myyar.yar"; archiver.newArchiveFile(srcPaths, yarPath); System.out.println("over!!!"); } /** * 向归档文件中添加新文件 */ @Test public void addFile(){ Archiver archiver = new Archiver(); archiver.appendFile("D:\\others\\arch\\hi.txt","d:\\others\\arch\\myyar.yar" ); System.out.println("over"); } @Test public void unarchiveFile(){ Archiver archiver = new Archiver(); archiver.unarchive("d:\\others\\arch\\myyar.yar","d:\\others\\arch\\unarch\\" ); System.out.println("over"); } }