java黑皮书25.18-19----(压缩与解压),带界面,概念版
问题描述
提示:运用霍夫曼编码压缩
实现压缩与解压缩
难点分析:
提示:我们自带了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----(压缩与解压),带界面,概念版相关推荐
- 压缩或者解压带密码的ZIp包
法一: 引用Ionip.ZIP.DLll /// <summary> /// 压缩文件夹 /// </summary> /// ...
- java实现文件压缩与解压
用java实现文件的压缩与解压是很常见的功能. 我最爱上代码: 1 import java.io.File; 2 import java.util.ArrayList; 3 import java.u ...
- Java 使用 zip4j 进行基本的压缩、解压、设置密码操作(version zip4j-2.6.4)
先看工具类 package space.util;import java.io.File; import java.util.List;import net.lingala.zip4j.ZipFile ...
- Java 中调用 Apache API 实现图片文件的 压缩 与 解压 实例
< Java 中调用 Apache API 实现图片文件的 压缩 与 解压 > 为什么不直接使用 Java JDK 中自带的 API 呢?必须使用 Apache API 实现文件的压缩与解 ...
- Java实现文件压缩与解压[zip格式,gzip格式]
原文:http://www.cnblogs.com/visec479/p/4112881.html#3069573 Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个 ...
- java gzip 解压文件_Java实现文件压缩与解压[zip格式,gzip格式]
原文:http://www.cnblogs.com/visec479/p/4112881.html#3069573 Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个 ...
- Java Jar包的压缩、解压使用指南
转载自 Java Jar包的压缩.解压使用指南 什么是jar包 JAR(Java Archive)是Java的归档文件,它是一种与平台无关的文件格式,它允许将许多文件组合成一个压缩文件. 如何打/解包 ...
- java解压zip包_Java中文件的压缩与解压,每天进步一点点系列
使用java.util.zip包,实现文件的压缩与解压,并提供了下载方法 注意 无论是调用createNewFile()创建文件,还是在创建输出流时由输出流负责创建文件,都必须保证父路径已经存在,否则 ...
- 使用java.util.zip包实现根据文件目录控制文件的压缩与解压
根据文件目录实现文件的压缩与解压 import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputSt ...
- java 压缩 空目录_java zip压缩与解压-支持空目录,保留文件修改时间
java zip压缩与解压-支持空目录,保留文件修改时间. 依赖于commons-io,commons-compress [Java]代码 import java.io.BufferedInputSt ...
最新文章
- 4.4 Triplet 损失-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
- 37 手游基于 Flink CDC + Hudi 湖仓一体方案实践
- mysql 按小时统计
- ubuntu下vscode编写cgo程序
- 20121214收藏
- ffmpeg 分割和合并
- 显示计算机101代码,电脑出现蓝屏故障101停机码,怎么解决问题
- android常用adb命令大全,Android ADB常用命令总结
- 矩阵求导——Numerator Layout Denominator Layout
- oracle sql 不等 优化6,oracle sql 优化(三)
- ajax与Java后台互相传数据
- JavaScript 正则表达式实现表单验证
- Linux中:wq :wq! :q :q!的区别
- Oracle-08:连接查询
- 架构三要素:职责明确的模块或者组件、关联关系、约束和指导原则
- 软件项目管理系统-经费报销-出差费
- 微信公众号开发——项目搭建
- 团队-排课软件-需求分析
- oracle awr详解
- 2022-4-24 Leetcode 300.最长递增子序列
热门文章
- 201571030337/201571030327——《小学生四则运算》结对项目报告
- python中的reshape是什么意思_python中reshape的用法(深度学习入门程序)
- text-decoration 属性的简单介绍
- 号称下一代监控系统,到底有多牛逼!
- 关于CMD文件中文乱码的解决方案
- 不同局域网ubuntu如何进行ssh穿透登录
- networkx 有向图强连通_有向图的强连通分支
- usart串口发送与接收问题
- web前端大作业 (仿英雄联盟网站制作HTML+CSS+JavaScript) 学生dreamweaver网页设计作业
- 环回接口---loopback