实验四、基于 Lempel-Ziv 算法的英文文本文件压缩

实验目的
一、通过设计计算机程序,实现基于 Lempel-Ziv 算法的英文文本文件压缩,进
一步理解 Lempel-Ziv 算法的意义。
二、熟练运用二进制数据文件的读写操作。
三、学习程序调试技术,进一步提高程序调试技能。
实验内容
教材里的 Lempel-Ziv 算法是针对二进制比特序列的编码而设计的,但算法的思想完全可以用于非二进制序列的编码。本次实验就是要利用 Lempel-Ziv 算法的思想,将英文文本文件看作是英文字符序列,实现英文文本文件的压缩。
一、编码算法思想:
1)建立一个只包含“空前缀串”的字典;将文本文件读入缓冲区,然后将当前编码指针指向第一个字符。
2)从当前编码指针所指的字符开始,用它及后面所有字符作为一个字符串,在字典中查找能与该字符串的前缀匹配的最长前缀串;
若没有匹配,则将“空前缀串”的编号0作为当前码字中的编号部分,再将当前编码指针所指的输入字符“A”作为当前码字中的符号部分。输出当前码字,然后编码指针指向下一个字符;
若有匹配的前缀串,则寻找最长匹配的前缀串,然后将该最长匹配前缀串在字典中的编号作为当前码字中的编号部分,再将当前输入序列中,与该前缀串匹配结束后的第一个字符“A”作为当前码字的符号部分。输出当前码字,再将编码指针指向字符“A”之后的第一个字符。

3)将上一步中,最长匹配前缀串加上字符“A”作为一个新的前缀串添加到字典中;若上一步中没有找到匹配的前缀串,则将“空前缀串”加上字符“A”作为新前缀串,实际就是将字符“A”本身添加到字典中。该前缀串编号为现有前缀串的最大编号加一。

4)4)若输入字符串没有处理完,则回到步骤 2),否则结束编码。
二、解码算法思想:
1)建立一个只包含“空前缀串”的字典;将压缩文件读入输入缓冲区,取第一个码字
2)在字典中查找当前码字中编号对应的前缀串,加上当前码字中的字符“A”后,将得到的字符串保存到输出缓冲区中。
3)再将这个字符串作为一个新的前缀串添加到字典中,该前缀串编号为现有前缀串的最大编号加一。
4)若码字处理完则结束,否则取下一个码字然后回到步骤 2)。
要求:
字典尺寸:65536;前缀串编号二进制比特数:16;字符“A”占一个字节。因此编码输出的每个码字为 3 个字节。
提示:
字典的每一个条目不一定要实际保存每一个前缀串本身,只需保存对应前缀串在输入缓冲区(编码方)或输出缓冲区(解码方)中的起始位置和长度就行。
实验任务:

  1. 设计编码程序。
  2. 在不用解码程序的情况下,以调试的手段说明编码程序是基本正确的。
  3. 设计解码程序。
  4. 在不比较重建序列和原始序列的情况下,以调试的手段说明解码程序是基本正确的。
package com.atguigu.java;import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Lempel-Ziv 算法的英文文本文件压缩*/
public class LZ {public static List<byte[]> compress(char[] text, String filePath) throws IOException {//定义属性 dictionary 用来存放字符串编码表Map<String, Integer> dictionary = new HashMap<>();List<byte[]> compressList = new ArrayList<>();// 将需要压缩的文本文件//定义一个空字符串//todo  这里定义的String 字符串产生了大量大垃圾其实可以优化//String str = "";StringBuilder str = new StringBuilder();for (int i = 0; i<text.length-1; i++) {str.append(text[i]);//控制 dictionary 的大小, dictionary大小没有超过 65535时,就一直往里面putif(dictionary.size() < 65535) {// 如果字典不包含 没有匹配到if (!dictionary.containsKey(str.toString())) {//把当前码子输出到缓冲区compressList.add(IntegerStr2Byte(0,str.toString()));// 把没有匹配到的字符串添加到字典中dictionary.put(str.toString(), dictionary.size()+1);// 字符串str清空,指针指向一下一个字符str.delete(0,str.length());//3 . 第一次进来需要put A 字符 入 字典
//                    if(!dictionary.containsKey("A"))
//                        dictionary.put("A",dictionary.size());} else {// 2. 若匹配到最长字符串while(dictionary.containsKey(str.toString())){i++;str.append(text[i]);}String s = str.substring(0,str.length()-1);String s1 = str.substring(str.length()-1,str.length());// 把对应的编码添加的输出缓存区compressList.add(IntegerStr2Byte(dictionary.get(s), s1));// 字典中添加上 最大匹配串+下一字符dictionary.put(str.toString(),dictionary.size()+1);str.delete(0, str.length());}}else {// 如果大于 65535时, 字典不能再添加文件了,此刻只能从字典中找while(dictionary.containsKey(str.toString())){if (i < text.length-1){i++;str.append(text[i]);}else {break;}}String s = str.substring(0,str.length()-1);String s1 = str.substring(str.length()-1,str.length());// 把对应的编码添加的输出缓存区compressList.add(IntegerStr2Byte(dictionary.get(s), s1));str.delete(0, str.length());}}// 调用写二进制文件方法生成压缩文件outByFileDataOutputStream(filePath, compressList);return compressList;}/*** 工具方法* @param integer* @param string* @return*/private static byte[] IntegerStr2Byte(Integer integer,String string){byte[] bytes = new byte[3];bytes[0] = (byte) (integer / 256);bytes[1] = (byte) (integer % 256);bytes[2] = string.getBytes()[0];return bytes;}/*** 保存压缩文件* @param filePath*/private static void outByFileDataOutputStream(String filePath, List<byte[]> compressList ) {File target = new File(filePath);if (target.exists() && target.isFile()){boolean flag = target.delete();}try {if (target.createNewFile()){for (byte[] bytes : compressList) {DataOutputStream out = new DataOutputStream(new FileOutputStream(filePath, true));out.write(bytes);out.close();}}} catch (IOException e) {e.printStackTrace();}}/*** 解压压缩文件* @param compressText* @throws IOException*/public static void unCompress(List<byte []> compressText,String filePath) throws IOException {//定义属性 dictionary 用来存放字符串编码表Map<Integer, String> dictionary = new HashMap<>();// 用来存放解码后的字符串StringBuilder Stringbuilder = new StringBuilder();for (byte [] bytes: compressText) {Integer integer = (bytes[0]&0x0FF) *256+ (bytes[1]&0x0FF);char c = (char)(int)bytes[2];//字典中没有把这个代码放进字典if (!dictionary.containsKey(integer)){//添加到输入缓存区Stringbuilder.append(c);//添加到字典中if (dictionary.size()< 65535)dictionary.put( dictionary.size()+1, String.valueOf(c));}else{if (dictionary.size() == 65535)//添加到输入缓存区Stringbuilder.append(dictionary.get(integer)+String.valueOf(c));//添加到字典中if (dictionary.size()< 65535)dictionary.put(dictionary.size()+1, dictionary.get(integer)+String.valueOf(c));}}FileWriter fw = new FileWriter(new File(filePath));fw.write(Stringbuilder.toString());//  在这里不关闭文件的话,会有一部分字符串没有写到文件中,可以调用 fw.flush(); 获取 close() 方法都能够把内容中的内容真正写到文件中fw.close();//        // 把编码表 dictionary key value 互换  方便取数据
//        Map<Integer, String> dictionary1 = new HashMap<>();
//        for(Map.Entry<String, Integer> entry : dictionary.entrySet()){//            dictionary1.put(entry.getValue(),entry.getKey());
//        }//        for (byte []: compressText) {//            Stringbuilder.append(dictionary1.get(ii));
//        }}/*** 读取text文件* @param fileName* @return*/public static String readFileContent(String fileName) {File file = new File(fileName);BufferedReader reader = null;StringBuffer sbf = new StringBuffer();try {reader = new BufferedReader(new FileReader(file));String tempStr;while ((tempStr = reader.readLine()) != null) {sbf.append(tempStr);}reader.close();return sbf.toString();} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {try {reader.close();} catch (IOException e1) {e1.printStackTrace();}}}return sbf.toString();}/*** 主函数* @param args* @throws IOException*/public static void main(String[] args) throws IOException {// 读取text文件String s = readFileContent("E:\\test.txt");List<byte[]> compress = compress(s.toCharArray(), "E:\\compress.LZ");unCompress(compress,"E:\\generate.txt");//读取待压缩的文本文件加载到缓冲区//把缓冲区内容传入compress方法中进行压缩//把压缩过的内容传入解压缩方法中进行解压缩还原文本文件}}

Java Lempel-Ziv相关推荐

  1. lempel ziv matlab,基于Python的LempelZiv算法的熵估计

    此函数允许估计时间序列的熵.它基于Lempel-Ziv压缩算法.对于长度为n的时间序列,熵估计为: E=(1/n和L_i)^-1 ln(n) 式中,L逯i是从位置i开始的最短子串的长度,该子串之前没有 ...

  2. 数据压缩及解压缩算法,多种文件的压缩与解压缩-java android

    > 数据压缩算法,文本压缩算法 几种压缩算法原理介绍- https://blog.csdn.net/clevercode/article/details/46691645 文本压缩算法的对比和选 ...

  3. 深入SecureFile—新一代LOB揭秘000

    编写人:常伟俊 审核人:张陈亚 在Oracle8i 中,LOB 设计是基于下列假设做出的: (1) LOB 实例化的大小预计为几个兆字节. (2) LOB 通常被视为"单写多读"类 ...

  4. linux c语言lzma,LZMA 算法简介

    The Lempel–Ziv–Markov chain algorithm (LZMA) is an algorithm used to perform lossless data compressi ...

  5. 7zip核心算法LZMA源码分析心得

    7zip核心算法LZMA分析心得 最近有空就研究了一下DEFLATE的LZ77压缩算法实现及7zip的LZMA压缩算法实现,现在记下相关心得如下: 一. DEFLATE中的LZ77算法实现比较简单,具 ...

  6. 《计算机科学导论》一导读

    前 言 Foundations of Computer Science, Third Edition 计算机在我们的日常生活中扮演了一个重要的角色,而且在未来也将一样.计算机科学是一个充满了挑战和发展 ...

  7. 读书笔记——计算机科学导论

    计算机科学导论-读书笔记 第一章 绪论 一.学习目标 1.定义计算机的图灵模型, 2.定义计算机的冯诺依曼模型 3.描述计算机的三大部分:硬件.数据和软件 4.列举与计算机硬件.软件.数据相关的话题 ...

  8. 看我们如何“把大象放进冰箱里”

    一.数学家的办法 转自MITBBS 把大象放到冰箱里的分析学方法 1)先把大象微分,然后把它放到冰箱里,再在冰箱里把它积分. 2)重新定义冰箱或者大象的测度(如Radon测度). 3)用Banach- ...

  9. 在1 MB RAM中排序100万个8位数字

    本文翻译自:Sorting 1 million 8-digit numbers in 1 MB of RAM I have a computer with 1 MB of RAM and no oth ...

  10. 为什么倒排索引不采用zlib这样的字典压缩算法——因为没法直接使用啊

    看了下压缩算法的发展历史,根据倒排索引的数据结构特点,个人认为zstd不适合做倒排索引压缩,举例说明下: 假设有一份文档倒排列表为:[300, 302, 303, 332],对于这组倒排数据,是没法* ...

最新文章

  1. React 项目----setState 方法修改 state (16)
  2. 六、使用数组模拟栈的思路及代码实现
  3. 深度解析:mPaaS 3.0全新组件
  4. 【转载】在华为敲代码那些年,我知道的这些事
  5. 九九乘法表c语言编程伪代码,py_11分支和循环
  6. mysql extis_SQL -- 联接查询,子查询,Extis 效率浅析
  7. java 注解 target_详解JDK 5 Annotation 注解之@Target的用法
  8. 手把手FFmpeg入门——视频解码+解封装
  9. model.evaluate 输出出一大串 ======================
  10. oracle erp 操作手册,OracleERP操作手册
  11. Windows下有关(下载与播放)软件
  12. web测试之功能测试总结
  13. 服务器2003设置共享文件夹共享文件夹,WinServer2003 文件夹共享 方法设置
  14. vue+croppr.js 裁剪圆形图片
  15. 谁能和乔布斯比勤奋?乔布斯的睡眠时间
  16. Sentinel SuperPro加密锁编程开发
  17. QQ聊天记录备份助手 v1.0——搜索、备份、恢复QQ聊天记录文件,重装系统必备...
  18. 如何使用Keil5中的虚拟示波器进行软件仿真
  19. java中singleton_java中singleton的几种实现方式
  20. FFmpeg的HEVC解码器源代码简单分析:解码器主干部分

热门文章

  1. maven创建eclipse wtp项目
  2. Nginx搭建虚拟主机环境
  3. 李宏毅(2020)作业2-hw2_classification
  4. Unity EmbeddedBrowser浏览器插件事件通讯
  5. SVN_处理文件误删恢复
  6. 测试用例 测试的方法
  7. 【Burp suite】intruder内的四种攻击模式(attack type)分析!
  8. iView组件+Django实现前后端分离上传图片
  9. 反反爬技术,破解猫眼网加密数字
  10. ping: www.baidu.com: 域名解析暂时失败 简单解决