/*** 压缩的文件操作** @author king**/public class CompressFileOption {/*** 读取文件** @param path* :文件路径* @return:将文件的内容以字节数组的样式返回*/public static byte[] readFile(String path) {byte[] dataByte = null;try {java.io.FileInputStream fis = new java.io.FileInputStream(path);int size = fis.available();// 可读的字节数dataByte = new byte[size];fis.read(dataByte);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return dataByte;}/*** 将码表的相关信息写入文件** @param fileSize* :原文件大小* @param map* :存放码表的map* @param listCh* :存放关键码的字符队列* @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));// 将每个字节写入文件String hfmcode_next = map.get(listBy.get(i));// 得到每个字节对应的哈夫曼编码byte codeSize = (byte) hfmcode_next.length();// 每个字节对应的哈夫曼编码大小fos.write(codeSize);// 将每个字节对应的哈夫曼编码大小写入文件dos.writeChars(hfmcode_next);// 将每个字符对应的哈夫曼编码写入文件}dos.flush();fos.close();}/*** 将压缩好的字节数组写入文件** @param b* :压缩好的字节数组* @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);// 写入字节数组的大小dos.writeInt(b.length);fos.write(b);fos.flush();fos.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 将10字符串转化为一个字节** @param str* :传入的字符串* @return:一个字节*/private byte CharArrayToByte(String str) {char[] c = str.toCharArray();// 将字符串str转化为字符数组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));// 幂计算value = (byte) (value + value_next);}return value;}/*** 将10字符串以8个为一组转化为一个字节数组** @param str* @return*/private byte[] StringToByteArray(String str) {char[] c = str.toCharArray();// 将字节串str转化为字符数组cint len = c.length;// 字符串字符的个数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 + "个字符串:" + s);b[i] = CharArrayToByte(s);s = "";System.out.println("第" + i + "个字符串转化为字节后的值:" + b[i]);}b[lenByte - 1] = 0;// 字节数组的最后一个存放补0的个数} else {// 如果字符串的长度不能被8整除lenByte = len / 8 + 2;b = new byte[lenByte];int remainder = len % 8;// 求出除8的余数int zeroNum = 8 - remainder;// 补0的个数System.out.println("补0数:" + zeroNum);System.out.println("原字符串:" + str);for (int i = 0; i < zeroNum; i++) {str = str + '0';// 在字符串后面补0}System.out.println("补0后的字符串:" + str);c = str.toCharArray();System.out.println("补0后的字符串的字符个数:" + 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 + "个字符串:" + s);b[i] = CharArrayToByte(s);s = "";System.out.println("第" + i + "个字符串转化为字节后的值:" + b[i]);}b[lenByte - 1] = (byte) zeroNum;// 字节数组的最后一个存放补0的个数}return b;}/*** 压缩文件** @param path1* :原文件路径* @param path2* :压缩后的文件路径* @throws Exception*/public void CompressFile(String path1, String path2) throws Exception {// 从文件中得到字节数组byte[] b = CompressFileOption.readFile(path1);int b_size = b.length;// 原文件大小byte[] b_compress;// 字节数组,存放压缩的字符串String hfmcode = "";// 文件内所有字节的哈夫曼编码String hfmcode_next;// 文件中每个字节的哈夫曼编码// 计算字符串中每个字节的权值,并返回一个存放字节和它对应权值的节点队列List<TreeNode> list = calWeight.calweight(b);int size = list.size();Huffman hfm = new Huffman();// 构建哈夫曼树并返回根节点TreeNode root = hfm.createHuffman(list);// 创建哈夫曼编码使其与字符一一对应hfm.createHfmCode(root, "");java.util.HashMap<Byte, String> map = hfm.getMap();// 得到码表List<Byte> listBy = hfm.getList();// 得到存放关键码队列System.out.println("mapsize---->:" + map.size());System.out.println("b---->:" + b.length);for (int i = 0; i < b_size; i++) {// 得到每个字节的哈夫曼编码hfmcode_next = map.get(b[i]);System.out.println("第"+i+"个: " + b[i] + "的编码:" + hfmcode_next);hfmcode = hfmcode + hfmcode_next;// 将每个字节的哈夫曼编码依次相加为一个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);// 得到字节数组for (int i = 0; i < b_compress.length; i++) {System.out.println("第" + i + "个字节" + b_compress[i]);}// 将文件大小和码表相关信息写入文件writeMap(b_size, map, listBy, path2);// 将字节数组写入文件writeFile(b_compress, path2);}
/*** 解压缩的文件操作** @author king**/public class UncompressFileOption {public static long fileSize;/*** 将8位10字符串前面缺0的补上0** @param str* @return*/private String addZero(String str) {int strLen = str.length();int zeroNum;if (strLen < 8) {// 若字符串长度小于8则补0zeroNum = 8 - strLen;for (int i = 0; i < zeroNum; i++) {str = "0" + str;}}return str;}/*** 将整型数组还原成之前的10串,即文件内容的哈夫曼编码** @param n* @return*/private String InttoBinaryString(int[] n) {int len = n.length;String[] s = new String[len];// 一个字符串数组存放二进制数据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("二进制形式表示:" + BinaryStr);int BinaryStrLen = BinaryStr.length();// 得到为减0前的字符串大小int zeroSub = n[len - 1];// 之前在末尾补0的个数,现在减去System.out.println("减0前的字符串大小:" + BinaryStrLen);System.out.println("需要在字符串末尾减0的个数表示:" + zeroSub);BinaryStr = BinaryStr.substring(0, BinaryStrLen - zeroSub);System.out.println("减0后的字符串大小:" + (BinaryStrLen - zeroSub));System.out.println("减0后的二进制形式表示:" + 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("数组p的长度:" + p.length);// System.out.println("数组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;// 有一个字符不匹配则跳出循环}}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];// 创建一个字符数组,存放码表中的字节byte codeSize;// 每个字节对应的哈夫曼编码大小String hfmcode_next = "";// 读取码表内容for (int i = 0; i < mapSize; i++) {mapKey[i] = (byte) fis.read();// 得到第i个字节codeSize = (byte) fis.read();// 得到每个字节对应的哈夫曼编码大小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();// 得到压缩好的字节数组的大小System.out.println("压缩好的字节数组的大小: " + len);byte[] b = new byte[len];// 字节数组,存放压缩的字节串int[] n = new int[len];// 整型数组fis.read(b);// 得到压缩好的文件的字节数组for (int i = 0; i < b.length; i++) {System.out.println("第" + i + "个字节:" + b[i]);// 将字节还原成原来的整型数据if (b[i] < 0) {n[i] = b[i] + 256;} else {n[i] = b[i];}System.out.println("第" + i + "个字节的整型表示:" + 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;// 记录文件当前是第几个字节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)) {// 若匹配// 一个字节字节的写入文件fos.write(mapKey[i]);count++;beginIndex = child.length();formerStr = formerStr.substring(beginIndex, endIndex);endIndex = endIndex - beginIndex;}}}fos.flush();fos.close();}
联系客服