Lample-Ziv文本压缩(java实现)--学习笔记

目的:通过设计计算机程序,实现基于Lempel-Ziv 算法的英文文本文件压缩。

编码算法思想:

1)建立一个只包含“空前缀串”的字典;将文本文件读入缓冲区,然后将当前编码指针指向第一个字符。

2)从当前编码指针所指的字符开始,用它及后面所有字符作为一个字符串,在字典中查找能与该字符串的前缀匹配的最长前缀串;若没有匹配,则将“空前缀串”的编号0 作为当前码字中的编号部分,再将当前编码指针所指的输入字符“A”作为当前码字中的符号部分。输出当前码字,然后编码指针指向下一个字符;若有匹配的前缀串,则寻找最长匹配的前缀串,然后将该最长匹配前缀串在字典中的编号作为当前码字中的编号部分,再将当前输入序列中,与该前缀串匹配结束后的第一个字符“A”作为当前码字的符号部分。输出当前码字,再将编码指针指向字符“A”之后的第一个字符。

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

4)若输入字符串没有处理完,则回到步骤2),否则结束编码。

说明:1、文本为英文文档。2、文档大小为53kb。

import java.io.*;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;

/**
 * info
 * author:Civil
 */
public class Encode {
    static byte[] data;
    static int[][] dictionary = new int[65536][2];
    static byte[] result = new byte[65536];
    static int out_adr = 0;//缓冲区地址起始位置

    public static void main(String[] args) {
        Instant start = Instant.now();
        Coding();
        Writing();
        Instant end = Instant.now();
        long timeElapsed = Duration.between(start, end).toMillis(); // 单位为毫秒
        System.out.println("编码完成!");
        System.out.println("耗时:" + timeElapsed + "ms");
    }

    static void Read() {
        try {
            File infile_path = new File("D:\\学习\\信息论\\题目\\c.txt");
            InputStream input = new FileInputStream(infile_path);
            data = input.readAllBytes();
            input.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void Coding() {
        Read();
        dictionary[0][0] = 0;//起始坐标
        dictionary[0][1] = 0;//字典长度
        byte high_adr = -128;//字典地址0--n个255--高位
        byte low_adr = -128;//字典地址1--n个1--低位
        byte follow_ele = -128;//后一个
        int dic_len = 1;//字典长度
        int Max_length = 0;//最长匹配字符串长度
        int dic_adr = 0;//字典地址
        int length = 1;//匹配字符串实际长度
        for (int i = 0; i < data.length; i=i+Max_length+1) {
            Max_length = 0;//则匹配长度还原
            for (int j = 0; j < dic_len; j++) {
                if ((data[i] == data[dictionary[j][0]]) && (dictionary[j][1] > 0)) {//有匹配
                    //末尾处理
                    if (i + dictionary[j][1] > data.length) {
                        continue;
                    } else {
                        for (int q = 1; q < dictionary[j][1]; q++) {//判断字典元素与数据流是否相等。如:111是否等于110
                            if (data[i + q] == data[dictionary[j][0] + q]) {
                                length++;//实际匹配长度
                            }
                        }
                        if ((dictionary[j][1] > Max_length) && (length == dictionary[j][1])) {//找最长匹配
                            Max_length = dictionary[j][1];//最长匹配长度
                            dic_adr = j;//最长匹配的字典地址
                        }
                        length = 1;//还原
                    }
                }
            }
            if ((Max_length == 0) | i == 0) {//空匹配{
                high_adr = -128;//byte类型取值范围是[-128,127],所以用-128代表0,用127代表255
                low_adr = -128;
                follow_ele = data[i];
                dictionary[dic_len][1] = 1;
            } else {//最长匹配
                if (i + Max_length < data.length) {
                    int ad0;
                    int ad1;
                    follow_ele = data[i + Max_length];
                    ad0 = dic_adr / 256 - 128;//[0,255]转[-128,127]--高位
                    ad1 = dic_adr % 256 - 128;//低位
                    high_adr = (byte) (ad0 >> 32);//int转byte
                    low_adr = (byte) (ad1 >> 32);
                    //更新字典
                    dictionary[dic_len][1] = Max_length + 1;
                }
            }
            //输出编码
            result[out_adr] = high_adr;
            result[out_adr + 1] = low_adr;
            result[out_adr + 2] = follow_ele;
            //更新字典
            dictionary[dic_len][0] = i;
            out_adr += 3;
            dic_len++;

        }
    }

    static void Writing() {
        try {
            File outfile_path = new File("D:\\学习\\信息论\\题目\\Coding.txt");
            OutputStream output = new FileOutputStream(outfile_path);
            byte[] out = Arrays.copyOfRange(result, 0, out_adr);
            output.write(out);
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃折耳根

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值