All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mycomm.itool.compress.huffman.Huffman Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 jw362j.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mycomm.itool.compress.huffman;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 *
 * @author jw362j
 */
class Node {

    public Node left, right;
    public int source;
    public int weight;
    public String dest;

    public Node(int sour, int wei) {
        source = sour;
        weight = wei;
        left = right = null;
        dest = "";
    }
}

//写入文件的头信息
class Header implements Serializable {

    private static final long serialVersionUID = 1L;
    public String[] mp;

    public Header(String[] m) {
        mp = m;

    }
}

public class Huffman {

    public String[] mp;
    public int[] cnt;
    public String path;

    public Huffman(String path) {
        this.path = path;
        mp = new String[256];
        cnt = new int[256];
    }

    //封装了解压的方法
    public void unzip() throws FileNotFoundException, IOException, ClassNotFoundException {
        ObjectInputStream ins = new ObjectInputStream(new FileInputStream(new File(path)));
        FileOutputStream writer = new FileOutputStream(new File(path.substring(0, path.length() - 5)));
        Header zipFile = (Header) ins.readObject();

        Map mp = new HashMap();
        for (int i = 0; i < 256; i++) {
            if (zipFile.mp[i] != null) {
                mp.put(zipFile.mp[i], (char) i);
            }
        }

        String buff = "";
        byte[] bf = null;
        while (ins.available() >= 4) {

            if (ins.available() == 4) {
                bf = new byte[4];
                for (int i = 0; i < 4; i++) {
                    bf[i] = ins.readByte();
                }
                if (ins.available() == 0) {
                    break;
                }
                for (int j = 0; j < 4; j++) {
                    buff += b2s(bf[j]);
                    while (buff.length() > 256) {
                        String s = "";
                        int cnt = 0;
                        for (int i = 0; i < buff.length(); i++) {
                            s += buff.charAt(i);
                            if (mp.containsKey(s)) {
                                writer.write(mp.get(s));

                                cnt += s.length();
                                s = "";
                                break;
                            }
                        }
                        writer.flush();
                        buff = buff.substring(cnt, buff.length());
                    }
                }
            }
            byte c = ins.readByte();
            buff += b2s(c);
            while (buff.length() > 256) {
                String s = "";
                int cnt = 0;
                for (int i = 0; i < buff.length(); i++) {
                    s += buff.charAt(i);
                    if (mp.containsKey(s)) {
                        writer.write(mp.get(s));
                        cnt += s.length();
                        s = "";
                        break;
                    }
                }
                writer.flush();
                buff = buff.substring(cnt, buff.length());
            }

        }

        for (int i = 0; i < 4; i++) {
            if (bf[i] == 0) {
                buff += "0";
            } else if (bf[i] == 1) {
                buff += "1";
            }
        }

        String s = "";
        for (int i = 0; i < buff.length(); i++) {
            s += buff.charAt(i);
            if (mp.containsKey(s)) {
                writer.write(mp.get(s));
                s = "";
            }
        }
        writer.flush();
        writer.close();
        ins.close();
    }

    //封装了压缩的方法
    public void zip() throws IOException {
        readFrequency();
        huffmanEncrypt();
        FileInputStream ins = new FileInputStream(new File(path));
        Header zipFile = new Header(mp);
        ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream(path + ".huff"));
        ous.writeObject(zipFile);

        String buff = "";
        int c;
        while ((c = ins.read()) != -1) {
            buff += mp[c];
            while (buff.length() >= 8) {
                ous.writeByte((byte) (s2b(buff.substring(0, 8))));
                buff = buff.substring(8, buff.length());
            }
        }

        for (int i = 0; i < 4; i++) {
            if (i < buff.length()) {
                ous.writeByte(buff.charAt(i) - '0');
            } else {
                ous.writeByte(255);
            }
        }

        ous.flush();
        ous.close();
        ins.close();
    }

    //字节转二进制字符串
    public String b2s(byte c) {
        int cc = (c + 256) % 256;
        String s = "";
        while (cc > 0) {
            if (cc % 2 == 1) {
                s += "1";
            } else {
                s += "0";
            }
            cc /= 2;
        }
        while (s.length() < 8) {
            s += "0";
        }
        return s;
    }

    //二进制字符串转字节
    public byte s2b(String s) {
        byte c = 0;
        for (int i = 7; i >= 0; i--) {
            c *= 2;
            if (s.charAt(i) == '1') {
                c += 1;
            }

        }
        return c;
    }

    // 读取文件,并获得每个字符的频数
    public void readFrequency() throws IOException {

        File file = new File(path);
        FileInputStream ins = new FileInputStream(file);
        int c;
        while ((c = ins.read()) != -1) {
            cnt[c] += 1;
        }
        ins.close();
    }

    // 读取频数,返回Huffman映射表
    public void huffmanEncrypt() {

        PriorityQueue pq = new PriorityQueue(256, new Comparator() {

            @Override
            public int compare(Node o1, Node o2) {

                return o1.weight - o2.weight;
            }

        });
        int times = 0;
        for (int i = 0; i < 256; i++) {
            if (cnt[i] > 0.5) {
                pq.add(new Node(i, cnt[i]));
                times++;
            }
        }

        for (int i = 0; i < times - 1; i++) {
            Node nodeFir, nodeSec;
            nodeFir = pq.poll();
            nodeSec = pq.poll();
            Node newNode = new Node(-1, nodeSec.weight + nodeFir.weight);
            newNode.left = nodeSec;
            newNode.right = nodeFir;
            pq.add(newNode);
        }

        Node root = pq.poll();
        Queue q = new LinkedBlockingQueue();
        q.add(root);
        while (!q.isEmpty()) {
            Node cur = q.poll(); // bfs遍历
            if (cur.source == -1) { // 非叶子节点
                if (cur.left != null) {
                    cur.left.dest = cur.dest + "1";
                    q.add(cur.left);
                }
                if (cur.right != null) {
                    cur.right.dest = cur.dest + "0";
                    q.add(cur.right);
                }
            } else { // 叶子节点
                mp[cur.source] = cur.dest;
            }
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Huffman huff = new Huffman("C:\\Users\\Administrator\\Desktop\\in.txt.huff");

        huff.unzip();

        //Huffman huff = new Huffman("C:\\Users\\Administrator\\Desktop\\in.txt");
        //huff.zip();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy