/*** 壓縮的文件操作** @author king**/public class CompressFileOption {/*** 讀取文件** @param path* :文件路徑* @return:將文件的內(nèi)容以字節(jié)數(shù)組的樣式返回*/public static byte[] readFile(String path) {byte[] dataByte = null;try {java.io.FileInputStream fis = new java.io.FileInputStream(path);int size = fis.available();// 可讀的字節(jié)數(shù)dataByte = new byte[size];fis.read(dataByte);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return dataByte;}/*** 將碼表的相關(guān)信息寫入文件** @param fileSize* :原文件大小* @param map* :存放碼表的map* @param listCh* :存放關(guān)鍵碼的字符隊(duì)列* @param path* :文件路徑* @throws Exception*/public static void writeMap(int fileSize,java.util.HashMap<Byte, String> map, List<Byte> listBy, String path)throws Exception {java.io.FileOutputStream fos = new java.io.FileOutputStream(path);java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);dos.writeInt(fileSize);// 將原文件大小寫入文件int mapSize = map.size();// 碼表的大小dos.writeInt(mapSize);// //將碼表的大小寫入文件for (int i = 0; i < mapSize; i++) {fos.write(listBy.get(i));// 將每個(gè)字節(jié)寫入文件String hfmcode_next = map.get(listBy.get(i));// 得到每個(gè)字節(jié)對應(yīng)的哈夫曼編碼byte codeSize = (byte) hfmcode_next.length();// 每個(gè)字節(jié)對應(yīng)的哈夫曼編碼大小fos.write(codeSize);// 將每個(gè)字節(jié)對應(yīng)的哈夫曼編碼大小寫入文件dos.writeChars(hfmcode_next);// 將每個(gè)字符對應(yīng)的哈夫曼編碼寫入文件}dos.flush();fos.close();}/*** 將壓縮好的字節(jié)數(shù)組寫入文件** @param b* :壓縮好的字節(jié)數(shù)組* @param path* :文件路徑*/public static void writeFile(byte[] b, String path) {try {java.io.FileOutputStream fos = new java.io.FileOutputStream(path,true);java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);// 寫入字節(jié)數(shù)組的大小dos.writeInt(b.length);fos.write(b);fos.flush();fos.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 將10字符串轉(zhuǎn)化為一個(gè)字節(jié)** @param str* :傳入的字符串* @return:一個(gè)字節(jié)*/private byte CharArrayToByte(String str) {char[] c = str.toCharArray();// 將字符串str轉(zhuǎn)化為字符數(shù)組cint len = c.length;byte[] b = new byte[len];byte value = 0;byte value_next;for (int i = 0; i < len; i++) {b[i] = Byte.parseByte(c[i] + "");// System.out.println(b[i]);}for (int i = 0; i < len; i++) {value_next = (byte) (b[i] * Math.pow(2, len - i - 1));// 冪計(jì)算value = (byte) (value + value_next);}return value;}/*** 將10字符串以8個(gè)為一組轉(zhuǎn)化為一個(gè)字節(jié)數(shù)組** @param str* @return*/private byte[] StringToByteArray(String str) {char[] c = str.toCharArray();// 將字節(jié)串str轉(zhuǎn)化為字符數(shù)組cint len = c.length;// 字符串字符的個(gè)數(shù)int lenByte;String s = "";char c_next;byte[] b;if (len % 8 == 0) {// 如果字符串的長度能被8整除lenByte = len / 8 + 1;b = new byte[lenByte];for (int i = 0; i < lenByte - 1; i++) {for (int j = i * 8; j < (i + 1) * 8; j++) {c_next = c[j];s = s + c_next;}System.out.println("第" + i + "個(gè)字符串:" + s);b[i] = CharArrayToByte(s);s = "";System.out.println("第" + i + "個(gè)字符串轉(zhuǎn)化為字節(jié)后的值:" + b[i]);}b[lenByte - 1] = 0;// 字節(jié)數(shù)組的最后一個(gè)存放補(bǔ)0的個(gè)數(shù)} else {// 如果字符串的長度不能被8整除lenByte = len / 8 + 2;b = new byte[lenByte];int remainder = len % 8;// 求出除8的余數(shù)int zeroNum = 8 - remainder;// 補(bǔ)0的個(gè)數(shù)System.out.println("補(bǔ)0數(shù):" + zeroNum);System.out.println("原字符串:" + str);for (int i = 0; i < zeroNum; i++) {str = str + '0';// 在字符串后面補(bǔ)0}System.out.println("補(bǔ)0后的字符串:" + str);c = str.toCharArray();System.out.println("補(bǔ)0后的字符串的字符個(gè)數(shù):" + c.length);for (int i = 0; i < lenByte - 1; i++) {for (int j = i * 8; j < (i + 1) * 8; j++) {c_next = c[j];s = s + c_next;}System.out.println("第" + i + "個(gè)字符串:" + s);b[i] = CharArrayToByte(s);s = "";System.out.println("第" + i + "個(gè)字符串轉(zhuǎn)化為字節(jié)后的值:" + b[i]);}b[lenByte - 1] = (byte) zeroNum;// 字節(jié)數(shù)組的最后一個(gè)存放補(bǔ)0的個(gè)數(shù)}return b;}/*** 壓縮文件** @param path1* :原文件路徑* @param path2* :壓縮后的文件路徑* @throws Exception*/public void CompressFile(String path1, String path2) throws Exception {// 從文件中得到字節(jié)數(shù)組byte[] b = CompressFileOption.readFile(path1);int b_size = b.length;// 原文件大小byte[] b_compress;// 字節(jié)數(shù)組,存放壓縮的字符串String hfmcode = "";// 文件內(nèi)所有字節(jié)的哈夫曼編碼String hfmcode_next;// 文件中每個(gè)字節(jié)的哈夫曼編碼// 計(jì)算字符串中每個(gè)字節(jié)的權(quán)值,并返回一個(gè)存放字節(jié)和它對應(yīng)權(quán)值的節(jié)點(diǎn)隊(duì)列List<TreeNode> list = calWeight.calweight(b);int size = list.size();Huffman hfm = new Huffman();// 構(gòu)建哈夫曼樹并返回根節(jié)點(diǎn)TreeNode root = hfm.createHuffman(list);// 創(chuàng)建哈夫曼編碼使其與字符一一對應(yīng)hfm.createHfmCode(root, "");java.util.HashMap<Byte, String> map = hfm.getMap();// 得到碼表List<Byte> listBy = hfm.getList();// 得到存放關(guān)鍵碼隊(duì)列System.out.println("mapsize---->:" + map.size());System.out.println("b---->:" + b.length);for (int i = 0; i < b_size; i++) {// 得到每個(gè)字節(jié)的哈夫曼編碼hfmcode_next = map.get(b[i]);System.out.println("第"+i+"個(gè): " + b[i] + "的編碼:" + hfmcode_next);hfmcode = hfmcode + hfmcode_next;// 將每個(gè)字節(jié)的哈夫曼編碼依次相加為一個(gè)01字符串}System.out.println("01串大?。? + hfmcode.length());System.out.println("01串:" + hfmcode);char[] ch = hfmcode.toCharArray();System.out.println("01串的大小:" + ch.length);b_compress = StringToByteArray(hfmcode);// 得到字節(jié)數(shù)組for (int i = 0; i < b_compress.length; i++) {System.out.println("第" + i + "個(gè)字節(jié)" + b_compress[i]);}// 將文件大小和碼表相關(guān)信息寫入文件writeMap(b_size, map, listBy, path2);// 將字節(jié)數(shù)組寫入文件writeFile(b_compress, path2);}
/*** 解壓縮的文件操作** @author king**/public class UncompressFileOption {public static long fileSize;/*** 將8位10字符串前面缺0的補(bǔ)上0** @param str* @return*/private String addZero(String str) {int strLen = str.length();int zeroNum;if (strLen < 8) {// 若字符串長度小于8則補(bǔ)0zeroNum = 8 - strLen;for (int i = 0; i < zeroNum; i++) {str = "0" + str;}}return str;}/*** 將整型數(shù)組還原成之前的10串,即文件內(nèi)容的哈夫曼編碼** @param n* @return*/private String InttoBinaryString(int[] n) {int len = n.length;String[] s = new String[len];// 一個(gè)字符串?dāng)?shù)組存放二進(jìn)制數(shù)據(jù)String BinaryStr = "";for (int i = 0; i < len - 1; i++) {s[i] = Integer.toBinaryString(n[i]);s[i] = addZero(s[i]);BinaryStr = BinaryStr + s[i];}System.out.println("二進(jìn)制形式表示:" + BinaryStr);int BinaryStrLen = BinaryStr.length();// 得到為減0前的字符串大小int zeroSub = n[len - 1];// 之前在末尾補(bǔ)0的個(gè)數(shù),現(xiàn)在減去System.out.println("減0前的字符串大小:" + BinaryStrLen);System.out.println("需要在字符串末尾減0的個(gè)數(shù)表示:" + zeroSub);BinaryStr = BinaryStr.substring(0, BinaryStrLen - zeroSub);System.out.println("減0后的字符串大小:" + (BinaryStrLen - zeroSub));System.out.println("減0后的二進(jìn)制形式表示:" + BinaryStr);return BinaryStr;}/*** 字符串匹配,判斷字符串child是否為parent的前子串** @param parent* @param child* @return*/private boolean StringMatch(String parent, String child) {char[] p = parent.toCharArray();char[] c = child.toCharArray();// System.out.println("數(shù)組p的長度:" + p.length);// System.out.println("數(shù)組c的長度:" + c.length);boolean b = false;for (int i = 0; i < c.length; i++) {if (c[i] == p[i]) {b = true;} else {b = false;break;// 有一個(gè)字符不匹配則跳出循環(huán)}}return b;}/*** 解壓縮文件** @param path2* :壓縮后的文件路徑* @param path3* :解壓縮后的文件路徑* @throws Exception*/public void UncompressFile(String path2, String path3) throws Exception {HashMap<Byte, String> map = new HashMap<Byte, String>();java.io.FileInputStream fis = new java.io.FileInputStream(path2);java.io.DataInputStream dis = new java.io.DataInputStream(fis);java.io.FileOutputStream fos = new java.io.FileOutputStream(path3);fileSize = dis.readInt();// 得到原文件的大小int mapSize = dis.readInt();// 得到碼表的大小byte[] mapKey = new byte[mapSize];// 創(chuàng)建一個(gè)字符數(shù)組,存放碼表中的字節(jié)byte codeSize;// 每個(gè)字節(jié)對應(yīng)的哈夫曼編碼大小String hfmcode_next = "";// 讀取碼表內(nèi)容for (int i = 0; i < mapSize; i++) {mapKey[i] = (byte) fis.read();// 得到第i個(gè)字節(jié)codeSize = (byte) fis.read();// 得到每個(gè)字節(jié)對應(yīng)的哈夫曼編碼大小char[] codeChar = new char[codeSize];for (int j = 0; j < codeSize; j++) {codeChar[j] = dis.readChar();hfmcode_next = hfmcode_next + codeChar[j];}map.put(mapKey[i], hfmcode_next);// 將鍵值對放入Map中hfmcode_next = "";}int len = dis.readInt();// 得到壓縮好的字節(jié)數(shù)組的大小System.out.println("壓縮好的字節(jié)數(shù)組的大小: " + len);byte[] b = new byte[len];// 字節(jié)數(shù)組,存放壓縮的字節(jié)串int[] n = new int[len];// 整型數(shù)組fis.read(b);// 得到壓縮好的文件的字節(jié)數(shù)組for (int i = 0; i < b.length; i++) {System.out.println("第" + i + "個(gè)字節(jié):" + b[i]);// 將字節(jié)還原成原來的整型數(shù)據(jù)if (b[i] < 0) {n[i] = b[i] + 256;} else {n[i] = b[i];}System.out.println("第" + i + "個(gè)字節(jié)的整型表示:" + n[i]);}String formerStr = InttoBinaryString(n);// 得到原10串System.out.println("formerStr:" + formerStr);int size = map.size();System.out.println("mapsize:" + size);int endIndex = formerStr.length();System.out.println("endIndex:" + endIndex);int beginIndex;// byte[] fileData = new byte[fileSize];int count = 0;// 記錄文件當(dāng)前是第幾個(gè)字節(jié)while (!formerStr.isEmpty()) {// 如果字符串不為空String child;for (int i = 0; i < mapKey.length; i++) {child = map.get(mapKey[i]);if (formerStr.isEmpty()) {// 若字符串為空break;}if (StringMatch(formerStr, child)) {// 若匹配// 一個(gè)字節(jié)字節(jié)的寫入文件fos.write(mapKey[i]);count++;beginIndex = child.length();formerStr = formerStr.substring(beginIndex, endIndex);endIndex = endIndex - beginIndex;}}}fos.flush();fos.close();}
聯(lián)系客服