数据结构与算法【Java】08---树结构的实际应用( 八 )

测试代码
//测试压缩文件String srcFile = "E:\\数据结构与算法学习\\myself\\owncode\\resources\\3.jpg";String dstFile ="E:\\数据结构与算法学习\\myself\\owncode\\resources\\3.zip";zipFile(srcFile,dstFile);System.out.println("压缩文件成功");
结果

数据结构与算法【Java】08---树结构的实际应用

文章插图
3.7、文件解压具体要求:将前面压缩的文件,重新恢复成原来的文件 。
思路:读取压缩文件(数据和赫夫曼编码表)-> 完成解压(文件恢复)
文件解压代码
//编写一个方法,完成对压缩文件的解压/** * * @param zipFile 准备解压的文件 * @param dstFile 将文件解压到哪个路径 */public static void unZipFile(String zipFile, String dstFile) {//定义文件输入流InputStream is = null;//定义一个对象输入流ObjectInputStream ois = null;//定义文件的输出流OutputStream os = null;try {//创建文件输入流is = new FileInputStream(zipFile);//创建一个和is关联的对象输入流ois = new ObjectInputStream(is);//读取byte数组huffmanBytesbyte[] huffmanBytes = (byte[])ois.readObject();//读取赫夫曼编码表Map<Byte,String> huffmanCodes = (Map<Byte,String>)ois.readObject();//解码byte[] bytes = decode(huffmanCodes, huffmanBytes);//将bytes 数组写入到目标文件os = new FileOutputStream(dstFile);//写数据到 dstFile 文件os.write(bytes);} catch (Exception e) {System.out.println(e.getMessage());} finally {try {os.close();ois.close();is.close();} catch (Exception e2) {System.out.println(e2.getMessage());}}}
测试代码
//测试解压文件String zipFile = "E:\\数据结构与算法学习\\myself\\owncode\\resources\\3.zip";String dstFile = "E:\\数据结构与算法学习\\myself\\owncode\\resources\\32.jpg";unZipFile(zipFile,dstFile);System.out.println("解压成功");
结果

数据结构与算法【Java】08---树结构的实际应用

文章插图
我们取文件夹中查看发现原始的图片和解压后的文件大小一样---->无损压缩
数据结构与算法【Java】08---树结构的实际应用

文章插图

数据结构与算法【Java】08---树结构的实际应用

文章插图
3.8、代码汇总我们将赫夫曼编码所有的代码进行汇总
package com.qjd.huffmancode;import java.io.*;import java.util.*;public class HuffmanCode {public static void main(String[] args) {/*String content = "i like like like java do you like a java";byte[] contentBytes = content.getBytes();System.out.println("原始的content字符串长度为:"+contentBytes.length);//40//压缩byte[] huffmanCodesBytes = huffmanZip(contentBytes);System.out.println("对content字符串压缩后的结果是:"+Arrays.toString(huffmanCodesBytes)+"长度为:"+huffmanCodesBytes.length);//解压byte[] sourceBytes = decode(huffmanCodes, huffmanCodesBytes);System.out.println("(解压后)原来的字符串="+new String(sourceBytes)+"长度为:"+new String(sourceBytes).length());*///测试压缩文件//String srcFile = "E:\\数据结构与算法学习\\myself\\owncode\\resources\\3.jpg";//String dstFile ="E:\\数据结构与算法学习\\myself\\owncode\\resources\\3.zip";//zipFile(srcFile,dstFile);//System.out.println("压缩文件成功");//测试解压文件String zipFile = "E:\\数据结构与算法学习\\myself\\owncode\\resources\\3.zip";String dstFile = "E:\\数据结构与算法学习\\myself\\owncode\\resources\\32.jpg";unZipFile(zipFile,dstFile);System.out.println("解压成功");}//编写一个方法,完成对压缩文件的解压/**** @param zipFile 准备解压的文件* @param dstFile 将文件解压到哪个路径*/public static void unZipFile(String zipFile, String dstFile) {//定义文件输入流InputStream is = null;//定义一个对象输入流ObjectInputStream ois = null;//定义文件的输出流OutputStream os = null;try {//创建文件输入流is = new FileInputStream(zipFile);//创建一个和is关联的对象输入流ois = new ObjectInputStream(is);//读取byte数组huffmanBytesbyte[] huffmanBytes = (byte[])ois.readObject();//读取赫夫曼编码表Map<Byte,String> huffmanCodes = (Map<Byte,String>)ois.readObject();//解码byte[] bytes = decode(huffmanCodes, huffmanBytes);//将bytes 数组写入到目标文件os = new FileOutputStream(dstFile);//写数据到 dstFile 文件os.write(bytes);} catch (Exception e) {System.out.println(e.getMessage());} finally {try {os.close();ois.close();is.close();} catch (Exception e2) {System.out.println(e2.getMessage());}}}//编写方法,将一个文件进行压缩/**** @param srcFile 你传入的希望压缩的文件的全路径* @param dstFile 我们压缩后将压缩文件放到哪个目录*/public static void zipFile(String srcFile, String dstFile) {//创建输出流OutputStream os = null;ObjectOutputStream oos = null;//创建文件的输入流FileInputStream is = null;try {//创建文件的输入流is = new FileInputStream(srcFile);//创建一个和源文件大小一样的byte[]byte[] b = new byte[is.available()];//读取文件is.read(b);//直接对源文件压缩byte[] huffmanBytes = huffmanZip(b);//创建文件的输出流, 存放压缩文件os = new FileOutputStream(dstFile);//创建一个和文件输出流关联的ObjectOutputStreamoos = new ObjectOutputStream(os);//把 赫夫曼编码后的字节数组写入压缩文件oos.writeObject(huffmanBytes);//这里我们以对象流的方式写入 赫夫曼编码 , 是为了以后我们恢复源文件时使用//注意一定要把赫夫曼编码 写入压缩文件oos.writeObject(huffmanCodes);}catch (Exception e) {System.out.println(e.getMessage());}finally {try {is.close();oos.close();os.close();}catch (Exception e) {System.out.println(e.getMessage());}}}//完成数据的解压//思路//1. 将huffmanCodeBytes [-88, -65, -56, -65, -56, -65, -55, 77, -57, 6, -24, -14, -117, -4, -60, -90, 28]//重新先转成 赫夫曼编码对应的二进制的字符串 "1010100010111..."//2.赫夫曼编码对应的二进制的字符串 "1010100010111..." =》 对照 赫夫曼编码=》 "i like like like java do you like a java"/*** 将一个byte 转成一个二进制的字符串,这里需要利用二进制的原码 , 反码,补码* @param b 传入的 byte* @param flag 标志是否需要补高位如果是true,表示需要补高位,如果是false表示不补, 如果是最后一个字节 , 无需补高位* @return 是该b 对应的二进制的字符串,(注意是按补码返回)*/private static String byteToBitString(boolean flag, byte b) {//使用变量保存 bint temp = b; //将 b 转成 int//如果是正数我们还存在补高位if(flag) {temp |= 256; //按位与 2561 0000 0000| 0000 0001 => 1 0000 0001}String str = Integer.toBinaryString(temp); //返回的是temp对应的二进制的补码if(flag) {return str.substring(str.length() - 8);} else {return str;}}//编写一个方法,完成对压缩数据的解码/**** @param huffmanCodes 赫夫曼编码表 map(key = value)* @param huffmanBytes 赫夫曼编码得到的字节数组* @return 就是原来的字符串对应的数组*/private static byte[] decode(Map<Byte,String> huffmanCodes, byte[] huffmanBytes) {//1. 先得到 huffmanBytes 对应的 二进制的字符串,形式 1010100010111...StringBuilder stringBuilder = new StringBuilder();//将byte数组转成二进制的字符串for(int i = 0; i < huffmanBytes.length; i++) {byte b = huffmanBytes[i];//判断是不是最后一个字节boolean flag = (i == huffmanBytes.length - 1);stringBuilder.append(byteToBitString(!flag, b));}//把字符串按照指定的赫夫曼编码进行解码//把赫夫曼编码表进行调换 , 因为反向查询 a->100 100->aMap<String, Byte>map = new HashMap<String,Byte>();for(Map.Entry<Byte, String> entry: huffmanCodes.entrySet()) {map.put(entry.getValue(), entry.getKey());//key = value变成 value = https://www.huyubaike.com/biancheng/key}//创建要给集合,存放byteList

推荐阅读