问题描述

提示:运用霍夫曼编码压缩

实现压缩与解压缩


难点分析:

提示:我们自带了Huffman编码

这里思路是1.读取文件到内存中;

2.调用霍夫曼编码方法将文件压缩成霍夫曼编码及其解码表

3.将解码表先写入压缩文件中

4.将霍夫曼编码先转换为十进制之后转换成对应的字符(ASCII码);

5.之后将字符写入就好

为什么要这么做?

例如 H------>110 ;  e------>10 ; l------>0 ; o------>111

Hello的霍夫曼编码是110100111,转换成字符是Ó,这样Hello五个字节就被压缩为了两个字节

使用方法:


这个程序对于有大量重复字节,中小型文件压缩还行,毕竟里面有解码表,所以对于Hello这样的文件压缩了还会大一些,但是如果一个文件有100Hello,压缩效果就出来了 。

代码:

提示:很鸡肋,压缩后自动退,压缩的文价与源文件同目录,同格式

package cn.edu.cqut;import java.io.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Scanner;import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;/*** 只能打开TXT文件。。。。。。之后改进~~~~~~~~*/public class Lab25_18ProMax extends Application {private static String choose;private static String sourceFile;private static String sub;public static void main(String[] args) throws IOException {launch(args);int a = sourceFile.lastIndexOf(sub);String src = sourceFile.substring(0, a);if (choose.equals("0")) {String targetFile = src + "Zip" + sub;Compression(sourceFile, targetFile);} else {String targetFile = src + "Unpack" + sub;unpack(sourceFile, targetFile);}System.out.println("欢迎下次使用^_^");}@Overridepublic void start(final Stage primaryStage) {BorderPane root = new BorderPane();Button buttonCompression = new Button("Compression");Button buttonUnpack = new Button("Unpack");HBox hBox = new HBox();hBox.setAlignment(Pos.CENTER);hBox.setSpacing(10);hBox.getChildren().add(buttonCompression);hBox.getChildren().add(buttonUnpack);HBox hBox1 = new HBox();hBox1.setAlignment(Pos.CENTER);Label label = new Label("Welcome to use XM Compression");label.setTextFill(Color.BLACK);label.setFont(new Font("Cambria", 30));hBox1.getChildren().add(label);buttonCompression.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent arg0) {FileChooser fileChooser = new FileChooser();FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("All files (*.*)", "*.*");fileChooser.getExtensionFilters().add(extFilter);File file = fileChooser.showOpenDialog(primaryStage);choose = "0";sourceFile = file.getAbsolutePath();sub = file.getName();primaryStage.close();}});buttonUnpack.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent arg0) {FileChooser fileChooser = new FileChooser();FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("All files (*.*)", "*.*");fileChooser.getExtensionFilters().add(extFilter);File file = fileChooser.showOpenDialog(primaryStage);choose = "1";sourceFile = file.getAbsolutePath();sub = file.getName();primaryStage.close();}});root.setTop(hBox1);root.setCenter(hBox);primaryStage.setScene(new Scene(root, 500, 400));primaryStage.show();}/*** 解压与压缩*///解压方法public static void unpack(String sourceFile, String targetFile) {String data = "";try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(sourceFile))) {while (true)data = data + objectInputStream.readUTF() + ";;";} catch (Exception e) {System.out.println("完成50%");}String[] wholeData = data.split(";;");//将码放到HashMap中int count = 0;HashMap<String, String> map = new HashMap<>();for (int i = 0; i < wholeData.length; i++) {if (wholeData[i].matches("([\\s\\S]*):(.*)")) {String[] temp = wholeData[i].split(":");map.put(temp[1], temp[0]);} else {count = i;break;}}//开始解码String textCode = "";String text;String English = "";if (wholeData[wholeData.length - 1].equals("1")) {for (int i = count; i < wholeData.length - 2; i++) {text = Integer.toBinaryString((wholeData[i]).charAt(0));while (text.length() != 8)text = "0" + text;textCode += text;}textCode += wholeData[wholeData.length - 2];String str = "";for (int i = 0; i < textCode.length(); i++) {str += textCode.charAt(i);if (map.containsKey(str)) {English += map.get(str);str = "";}}} else {for (int i = count; i < wholeData.length - 1; i++) {text = Integer.toBinaryString((wholeData[i]).charAt(0));if (text.length() == 8)textCode += text;elsetext = "0" + text;}String str = "";for (int i = 0; i < textCode.length(); i++) {str += textCode.charAt(i);if (map.containsKey(str)) {English += map.get(str);str = "";}}}try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(targetFile))) {objectOutputStream.writeUTF(English);objectOutputStream.flush();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//压缩方法public static void Compression(String sourceFile, String targetFile) throws IOException {//将霍夫曼编码输出HuffmanCodeForProMax huffmanCode = new HuffmanCodeForProMax();//读文件String[] codes;String textCode = "";int count = 0;String HuffmanCodes = "";byte[] bytes;try (FileInputStream input = new FileInputStream(sourceFile)) {bytes = new byte[input.available()];input.read(bytes);codes = huffmanCode.outPutHuffmanCode(bytes);}String mm = "";File fileText = new File(sourceFile);Scanner in = new Scanner(fileText);while (in.hasNext())mm += in.nextLine() + "\n";in.close();try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(targetFile))) {//解码表for (int i = 0; i < codes.length; i++) {if (codes[i] != null)output.writeUTF((char) i + ":" + codes[i]);// 这里为了方便之后解压所以写入 编码字母对应的ASCII码 + 霍夫曼编码 + "\n"}String[] nn = mm.split("\n");//数据码for (int i = 0; i < nn.length; i++) {String temp = nn[i];for (int j = 0; j < temp.length(); j++) {textCode += codes[temp.charAt(j)];}textCode += codes[10];}//写入二进制编码for (int i = 0; i < textCode.length(); i++) {HuffmanCodes += textCode.charAt(i);count++;if (count % 8 == 0) {char temp = (char) (Integer.parseInt(HuffmanCodes, 2));output.writeUTF(temp + " ");HuffmanCodes = "";}}if (HuffmanCodes.length() != 0) {output.writeUTF(HuffmanCodes);output.writeUTF("1");//the end has data} else {output.writeUTF("0");// the end not data}output.flush();}}}/*** 霍夫曼编码程序*/
class HuffmanCodeForProMax {public HuffmanCodeForProMax() {}//输出霍夫曼编码public String[] outPutHuffmanCode(byte[] bytes) {int[] counts = new int[256];for (int i = 0; i < bytes.length; i++)counts[bytes[i]]++;TreeForLab25_18 tree = getHuffmanTree(counts); // Create a Huffman treeString[] codes = getCode(tree.root); // Get codesreturn codes;}/*** Get Huffman codes for the characters This method is called once after a* Huffman tree is built*/public static String[] getCode(TreeForLab25_18.NodeForLab25_18 root) {if (root == null)return null;String[] codes = new String[2 * 128];assignCode(root, codes);return codes;}/* Recursively get codes to the leaf node */private static void assignCode(TreeForLab25_18.NodeForLab25_18 root, String[] codes) {if (root.left != null) {root.left.code = root.code + "0";assignCode(root.left, codes);root.right.code = root.code + "1";assignCode(root.right, codes);} else {codes[(int) root.element] = root.code;}}/*** Get a Huffman tree from the codes*/public static TreeForLab25_18 getHuffmanTree(int[] counts) {// Create a heap to hold treesHeapForLab25_18ProMax<TreeForLab25_18> heap = new HeapForLab25_18ProMax<TreeForLab25_18>(); // Defined in Listing 24.10for (int i = 0; i < counts.length; i++) {if (counts[i] > 0)heap.add(new TreeForLab25_18(counts[i], (char) i)); // A leaf node tree}while (heap.getSize() > 1) {TreeForLab25_18 t1 = heap.remove(); // Remove the smallest weight treeTreeForLab25_18 t2 = heap.remove(); // Remove the next smallest weightheap.add(new TreeForLab25_18(t1, t2)); // Combine two trees}return heap.remove(); // The final tree}/*** Get the frequency of the characters*/public static int[] getCharacterFrequency(String text) {int[] counts = new int[256]; // 256 ASCII charactersfor (int i = 0; i < text.length(); i++)counts[(int) text.charAt(i)]++; // Count the character in textreturn counts;}/*** Define a Huffman coding tree*/public static class TreeForLab25_18 implements Comparable<TreeForLab25_18> {NodeForLab25_18 root; // The root of the tree/*** Create a tree with two subtrees*/public TreeForLab25_18(TreeForLab25_18 t1, TreeForLab25_18 t2) {root = new NodeForLab25_18();root.left = t1.root;root.right = t2.root;root.weight = t1.root.weight + t2.root.weight;}/*** Create a tree containing a leaf node*/public TreeForLab25_18(int weight, char element) {root = new NodeForLab25_18(weight, element);}@Override/** Compare trees based on their weights */public int compareTo(TreeForLab25_18 t) {if (root.weight < t.root.weight) // Purposely reverse the orderreturn 1;else if (root.weight == t.root.weight)return 0;elsereturn -1;}public class NodeForLab25_18 {char element; // Stores the character for a leaf nodeint weight; // weight of the subtree rooted at this nodeNodeForLab25_18 left; // Reference to the left subtreeNodeForLab25_18 right; // Reference to the right subtreeString code = ""; // The code of this node from the root/*** Create an empty node*/public NodeForLab25_18() {}/*** Create a node with the specified weight and character*/public NodeForLab25_18(int weight, char element) {this.weight = weight;this.element = element;}}}
}/*** 这是对应程序的堆*/
class HeapForLab25_18ProMax<E> {private ArrayList<E> list = new ArrayList<>();private Comparator<? super E> c;public HeapForLab25_18ProMax() {this.c = (e1, e2) -> ((Comparable<E>) e1).compareTo(e2);}public HeapForLab25_18ProMax(Comparator<E> c) {this.c = c;}public HeapForLab25_18ProMax(E[] object) {this.c = (e1, e2) -> ((Comparable<E>) e1).compareTo(e2);for (int i = 0; i < object.length; i++) {add(object[i]);}}public void add(E newObject) {list.add(newObject);int currentIndex = list.size() - 1;while (currentIndex > 0) {int parentIndex = (currentIndex - 1) / 2;if (c.compare(list.get(currentIndex), list.get(parentIndex)) > 0) {E temp = list.get(currentIndex);list.set(currentIndex, list.get(parentIndex));list.set(parentIndex, temp);} elsebreak;//继续和下一个父节点比较currentIndex = parentIndex;}}public E remove() {if (list.size() == 0) return null;E removeObject = list.get(0);//将最后一个放到第一个list.set(0, list.get(list.size() - 1));list.remove(list.size() - 1);int currentIndex = 0;while (currentIndex < list.size()) {int leftChildIndex = 2 * currentIndex + 1;int rightChildIndex = 2 * currentIndex + 2;//边界条件以及找到最大的一个子节点if (leftChildIndex >= list.size()) break;int maxIndex = leftChildIndex;//这里预先指定和下面再次判断的目的是为了看是否存在右节点if (rightChildIndex < list.size()) {if (c.compare(list.get(maxIndex), list.get(rightChildIndex)) < 0) {maxIndex = rightChildIndex;}}//对比if (c.compare(list.get(currentIndex), list.get(maxIndex)) < 0) {E temp = list.get(maxIndex);list.set(maxIndex, list.get(currentIndex));list.set(currentIndex, temp);//这里得注意!!!,当前指针需要移动的currentIndex = maxIndex;} elsebreak;}return removeObject;}public int getSize() {return list.size();}public boolean isEmpty() {return list.size() == 0;}}

java黑皮书25.18-19----(压缩与解压),带界面,概念版相关推荐

  1. 压缩或者解压带密码的ZIp包

    法一: 引用Ionip.ZIP.DLll /// <summary>         /// 压缩文件夹         /// </summary>         /// ...

  2. java实现文件压缩与解压

    用java实现文件的压缩与解压是很常见的功能. 我最爱上代码: 1 import java.io.File; 2 import java.util.ArrayList; 3 import java.u ...

  3. Java 使用 zip4j 进行基本的压缩、解压、设置密码操作(version zip4j-2.6.4)

    先看工具类 package space.util;import java.io.File; import java.util.List;import net.lingala.zip4j.ZipFile ...

  4. Java 中调用 Apache API 实现图片文件的 压缩 与 解压 实例

    < Java 中调用 Apache API 实现图片文件的 压缩 与 解压 > 为什么不直接使用 Java JDK 中自带的 API 呢?必须使用 Apache API 实现文件的压缩与解 ...

  5. Java实现文件压缩与解压[zip格式,gzip格式]

    原文:http://www.cnblogs.com/visec479/p/4112881.html#3069573 Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个 ...

  6. java gzip 解压文件_Java实现文件压缩与解压[zip格式,gzip格式]

    原文:http://www.cnblogs.com/visec479/p/4112881.html#3069573 Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个 ...

  7. Java Jar包的压缩、解压使用指南

    转载自 Java Jar包的压缩.解压使用指南 什么是jar包 JAR(Java Archive)是Java的归档文件,它是一种与平台无关的文件格式,它允许将许多文件组合成一个压缩文件. 如何打/解包 ...

  8. java解压zip包_Java中文件的压缩与解压,每天进步一点点系列

    使用java.util.zip包,实现文件的压缩与解压,并提供了下载方法 注意 无论是调用createNewFile()创建文件,还是在创建输出流时由输出流负责创建文件,都必须保证父路径已经存在,否则 ...

  9. 使用java.util.zip包实现根据文件目录控制文件的压缩与解压

    根据文件目录实现文件的压缩与解压 import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputSt ...

  10. java 压缩 空目录_java zip压缩与解压-支持空目录,保留文件修改时间

    java zip压缩与解压-支持空目录,保留文件修改时间. 依赖于commons-io,commons-compress [Java]代码 import java.io.BufferedInputSt ...

最新文章

  1. 4.4 Triplet 损失-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  2. 37 手游基于 Flink CDC + Hudi 湖仓一体方案实践
  3. mysql 按小时统计
  4. ubuntu下vscode编写cgo程序
  5. 20121214收藏
  6. ffmpeg 分割和合并
  7. 显示计算机101代码,电脑出现蓝屏故障101停机码,怎么解决问题
  8. android常用adb命令大全,Android ADB常用命令总结
  9. 矩阵求导——Numerator Layout Denominator Layout
  10. oracle sql 不等 优化6,oracle sql 优化(三)
  11. ajax与Java后台互相传数据
  12. JavaScript 正则表达式实现表单验证
  13. Linux中:wq :wq! :q :q!的区别
  14. Oracle-08:连接查询
  15. 架构三要素:职责明确的模块或者组件、关联关系、约束和指导原则
  16. 软件项目管理系统-经费报销-出差费
  17. 微信公众号开发——项目搭建
  18. 团队-排课软件-需求分析
  19. oracle awr详解
  20. 2022-4-24 Leetcode 300.最长递增子序列

热门文章

  1. 201571030337/201571030327——《小学生四则运算》结对项目报告
  2. python中的reshape是什么意思_python中reshape的用法(深度学习入门程序)
  3. text-decoration 属性的简单介绍
  4. 号称下一代监控系统,到底有多牛逼!
  5. 关于CMD文件中文乱码的解决方案
  6. 不同局域网ubuntu如何进行ssh穿透登录
  7. networkx 有向图强连通_有向图的强连通分支
  8. usart串口发送与接收问题
  9. web前端大作业 (仿英雄联盟网站制作HTML+CSS+JavaScript) 学生dreamweaver网页设计作业
  10. 环回接口---loopback