Khatello ea data ka algorithm ea Huffman

ho kena

Sehloohong sena, ke tla bua ka algorithm e tsebahalang ea Huffman, hammoho le ts'ebeliso ea eona ho compression ea data.

Ka lebaka leo, re tla ngola archive e bonolo. Sena se se se ntse se le teng sengoloa se buang ka Habré, empa ntle le ts'ebetsong e sebetsang. Boitsebiso ba theory ea poso ea morao-rao bo nkiloe lithutong tsa saense tsa k'homphieutha tsa sekolo le buka ea Robert Laforet "Data Structures and Algorithms in Java". Kahoo, ntho e 'ngoe le e' ngoe e tlas'a sehiloeng!

Ho thuisa hanyane

Faeleng e tloaelehileng ea mongolo, tlhaku e le 'ngoe e kentsoe ka li-bits tse 8 (ASCII encoding) kapa 16 (Unicode encoding). Ka mor'a moo, re tla nahana ka khouto ea ASCII. Ka mohlala, nka khoele s1 = "SUSIE O RE HO BONOLO". Ka kakaretso, ho na le litlhaku tse 22 moleng, ehlile, ho kenyeletsoa libaka le sebapali sa newline - 'n'. Faele e nang le mohala ona e tla ba boima ba 22 * ​​8 = 176 bits. Potso e hlaha hang-hang: na hoa utloahala ho sebelisa likotoana tsohle tse 8 ho kenyelletsa tlhaku e le 'ngoe? Ha re sebelise litlhaku tsohle tsa ASCII. Esita le haeba ba ne ba le teng, e ne e tla ba ho utloahalang ho fana ka tlhaku e atisang ho hlaha - S - khoutu e khutšoanyane ka ho fetisisa, le bakeng sa tlhaku e sa tloaelehang - T (kapa U, kapa 'n') - fana ka khoutu e nepahetseng haholoanyane. Ena ke algorithm ea Huffman: o hloka ho fumana khetho e ntle ka ho fetisisa ea encoding, eo ho eona faele e tla ba boima ba bonyane. Ke ntho e tloaelehileng hore litlhaku tse fapaneng li tla ba le bolelele bo fapaneng ba khoutu - ona ke motheo oa algorithm.

Khoutu

Hobaneng o sa fe sebopeho 'S' khoutu, mohlala, bolelele ba 1 bit: 0 kapa 1. E ke e be 1. Joale tlhaku ea bobeli e hlahang ka ho fetisisa - '' (sebaka) - re tla fana ka 0. Nahana, u qalile ho hlaola molaetsa wa hao - khoele e kentsweng s1 - mme o bona hore khoutu e qala ka 1. Joale, seo u lokelang ho se etsa: na ke tlhaku S, kapa ke tlhaku e 'ngoe, joalo ka A? Ka hona, ho hlaha molao oa bohlokoa:

Ha ho khoutu e tlamehang ho ba sehlongoapele sa e 'ngoe

Molao ona ke senotlolo sa algorithm. Ka hona, ho theoa ha khoutu ho qala ka tafole ea khafetsa, e bonts'ang khafetsa (palo ea liketsahalo) ea letšoao le leng le le leng:

Khatello ea data ka algorithm ea Huffman Litlhaku tse hlahang hangata li tlameha ho kengoa ka tse fokolang haholo khoneha palo ea likotoana. Ke tla fana ka mohlala oa e 'ngoe ea litafole tsa khoutu tse ka khonehang:

Khatello ea data ka algorithm ea Huffman Kahoo molaetsa o kentsoeng o tla shebahala tjena:

10 01111 10 110 1111 00 10 010 1110 10 00 110 0110 00 110 10 00 1111 010 10 1110 01110

Ke arola khoutu ea motho ka mong ka sebaka. Sena se ke ke sa etsahala ka faele e hatisitsoeng!
Ho hlaha potso: ho tlile joang hore rookie ee e be le khoutu ea ho etsa tafole ea khoutu? Sena se tla tšohloa ka tlase.

Ho aha Sefate sa Huffman

Mona ke moo lifate tsa lipatlisiso tsa binary li tlang ho thusa. Seke oa tšoenyeha, u ke ke ua hloka ho batla, ho kenya, le ho hlakola mekhoa mona. Mona ke sebopeho sa sefate ho java:

public class Node {
    private int frequence;
    private char letter;
    private Node leftChild;
    private Node rightChild;
    ...
}

class BinaryTree {
    private Node root;

    public BinaryTree() {
        root = new Node();
    }
    public BinaryTree(Node root) {
        this.root = root;
    }
    ...
}

Ena ha se khoutu e felletseng, khoutu e felletseng e tla ba ka tlase.

Mona ke algorithm ea ho haha ​​​​sefate:

  1. Etsa ntho ea Node bakeng sa tlhaku e 'ngoe le e' ngoe e tsoang molaetseng (mola s1). Tabeng ea rona, ho tla ba le li-node tse 9 (Lintho tsa Node). Node ka 'ngoe e na le likarolo tse peli tsa data: letšoao le khafetsa
  2. Etsa ntho ea Sefate (BinaryTree) bakeng sa node e 'ngoe le e' ngoe ea Node. Node e fetoha motso oa sefate.
  3. Kenya lifate tsena moleng oa pele. Ha makhetlo a tlase a le tlase, maemo a tlang pele a phahame. Ka hona, ha ho ntšoa, sefate se nang le maqhubu a tlaase ka ho fetisisa se khethoa kamehla.

Ka mor'a moo, u lokela ho etsa cyclically etsa tse latelang:

  1. Fumana lifate tse peli ho tloha moleng oa pele 'me u li etse bana ba node e ncha (node ​​e sa tsoa thehoa ntle le tlhaku). Khafetsa ea node e ncha e lekana le kakaretso ea maqhubu a lifate tse peli tsa litloholo.
  2. Bakeng sa node ena, theha sefate se metse ka metso sebakeng sena. Kenya sefate sena morao moleng oa bohlokoa. (Kaha sefate se na le maqhubu a macha, ho ka etsahala hore se kene sebakeng se secha moleng)
  3. Tsoela pele mehato ea 1 le ea 2 ho fihlela sefate se le seng se sala moleng - sefate sa Huffman

Nahana ka algorithm ena moleng oa s1:

Khatello ea data ka algorithm ea Huffman

Mona letšoao "lf" (linefeed) le bolela mola o mocha, "sp" (sebaka) ke sebaka.

Ho latela eng?

Re na le sefate sa Huffman. HO LOKILE. Le ho etsa eng ka eona? Ba ke ke ba e nka mahala, 'me joale, u lokela ho latela litsela tsohle tse ka khonehang ho tloha motsong ho ea makhasi a sefate. Re lumellana ho beha moeli 0 haeba o lebisa ho ngoana ea letšehali le 1 haeba e lebisa ho ea nepahetseng. Ha re bua hantle, lintlheng tsena, khoutu ea sebopeho ke tsela ho tloha motsong oa sefate ho ea lekhasing le nang le sebopeho sena.

Khatello ea data ka algorithm ea Huffman

Kahoo, tafole ea likhoutu e ile ea hlaha. Hlokomela hore haeba re nahana ka tafole ena, re ka etsa qeto ea "boima" ba motho ka mong - ena ke bolelele ba khoutu ea eona. Joale, ka mokhoa o hatelitsoeng, faele ea mohloli e tla ba boima: 2 * 3 + 2 * 4 + 3 * 3 + 6 * 2 + 1 * 4 + 1 * 5 + 2 * 4 + 4 * 2 + 1 * 5 = 65 bits. . Qalong e ne e le boima ba likotoana tse 176. Ka hona, re ile ra e fokotsa ka makhetlo a 176/65 = 2.7! Empa sena ke utopia. Ho ke ke ha etsahala hore karo-karolelano e joalo e fumanoe. Hobaneng? Sena se tla tšohloa hamorao.

Decoding

Hantle, mohlomong ntho e bonolo ka ho fetisisa e setseng ke decoding. Ke nahana hore bongata ba lona le nahanne hore ha ho khonehe ho theha faele e hatelletsoeng ntle le lintlha tsa hore na e kentsoe joang - re ke ke ra khona ho e khetholla! Ee, ho ne ho le thata ho 'na ho hlokomela sena, empa ke tlameha ho theha tafole ea faele ea mongolo.txt ka tafole ea khatello:

01110
 00
A010
E1111
I110
S10
T0110
U01111
Y1110

Kenyo ea tafole ka mokhoa oa 'character'"character code". Ke hobane'ng ha 01110 e se na letšoao? Ebile, e na le lets'oao, lisebelisoa tsa java feela tseo ke li sebelisang ha ke hlahisa faele, sebapali sa newline - 'n' - se fetoleloa ho mola o mocha (ho sa tsotelehe hore na o utloahala o le bohlanya hakae). Ka hona, mohala o se nang letho ka holimo ke sebopeho sa khoutu 01110. Bakeng sa khoutu 00, sebopeho ke sebaka qalong ea mola. Ke tlameha ho bolela hang-hang hore mokhoa ona oa ho boloka tafole o ka bolela hore ke oona o sa utloahaleng ka ho fetisisa bakeng sa coefficient ea rona ea khan. Empa ho bonolo ho e utloisisa le ho e sebelisa. Ke tla thabela ho utloa likhothaletso tsa hau ho maikutlo mabapi le optimization.

Ka tafole ena, ho bonolo haholo ho e hlalosa. Ha re hopoleng hore na re ne re tataisoa ke molao ofe ha re theha khouto:

Ha ho khoutu e tlamehang ho ba sehlongoapele sa e 'ngoe

Mona ke moo e bapalang karolo ea ho thusa. Re bala hanyane ka hanyane ka tatellano, 'me hang ha khoele e hlahisoang ke d, e nang le likotoana tse baloang, e ts'oana le encoding e tsamaellanang le sebopeho sa sebapali, hang-hang rea tseba hore sebopeho sa sebopeho (le sona feela!) se kentsoe. Ka mor'a moo, re ngola litlhaku ho khoele ea decode (khoele e nang le molaetsa o hlalositsoeng), tsosolosa mohala oa d, 'me u bale faele e kentsoeng ho ea pele.

Ts'ebetsong

Ke nako ea ho nyenyefatsa khoutu ea ka ka ho ngola polokelo ea litaba. Ha re e bitse Compressor.

Qala hape. Pele ho tsohle, re ngola sehlopha sa Node:

public class Node {
    private int frequence;//частота
    private char letter;//буква
    private Node leftChild;//левый потомок
    private Node rightChild;//правый потомок

   

    public Node(char letter, int frequence) { //собственно, конструктор
        this.letter = letter;
        this.frequence = frequence;
    }

    public Node() {}//перегрузка конструтора для безымянных узлов(см. выше в разделе о построении дерева Хаффмана)
    public void addChild(Node newNode) {//добавить потомка
        if (leftChild == null)//если левый пустой=> правый тоже=> добавляем в левый
            leftChild = newNode;
        else {
            if (leftChild.getFrequence() <= newNode.getFrequence()) //в общем, левым потомком
                rightChild = newNode;//станет тот, у кого меньше частота
            else {
                rightChild = leftChild;
                leftChild = newNode;
            }
        }

        frequence += newNode.getFrequence();//итоговая частота
    }

    public Node getLeftChild() {
        return leftChild;
    }

    public Node getRightChild() {
        return rightChild;
    }

    public int getFrequence() {
        return frequence;
    }

    public char getLetter() {
        return letter;
    }

    public boolean isLeaf() {//проверка на лист
        return leftChild == null && rightChild == null;
    }
}

Joale sefate:

class BinaryTree {
    private Node root;

    public BinaryTree() {
        root = new Node();
    }

    public BinaryTree(Node root) {
        this.root = root;
    }

    public int getFrequence() {
        return root.getFrequence();
    }

    public Node getRoot() {
        return root;
    }
}

Lethathamo le tlang pele:

import java.util.ArrayList;//да-да, очередь будет на базе списка

class PriorityQueue {
    private ArrayList<BinaryTree> data;//список очереди
    private int nElems;//кол-во элементов в очереди

    public PriorityQueue() {
        data = new ArrayList<BinaryTree>();
        nElems = 0;
    }

    public void insert(BinaryTree newTree) {//вставка
        if (nElems == 0)
            data.add(newTree);
        else {
            for (int i = 0; i < nElems; i++) {
                if (data.get(i).getFrequence() > newTree.getFrequence()) {//если частота вставляемого дерева меньше 
                    data.add(i, newTree);//чем част. текущего, то cдвигаем все деревья на позициях справа на 1 ячейку                   
                    break;//затем ставим новое дерево на позицию текущего
                }
                if (i == nElems - 1) 
                    data.add(newTree);
            }
        }
        nElems++;//увеличиваем кол-во элементов на 1
    }

    public BinaryTree remove() {//удаление из очереди
        BinaryTree tmp = data.get(0);//копируем удаляемый элемент
        data.remove(0);//собственно, удаляем
        nElems--;//уменьшаем кол-во элементов на 1
        return tmp;//возвращаем удаленный элемент(элемент с наименьшей частотой)
    }
}

Sehlopha se bōpang sefate sa Huffman:

public class HuffmanTree {
    private final byte ENCODING_TABLE_SIZE = 127;//длина кодировочной таблицы
    private String myString;//сообщение
    private BinaryTree huffmanTree;//дерево Хаффмана
    private int[] freqArray;//частотная таблица
    private String[] encodingArray;//кодировочная таблица


    //----------------constructor----------------------
    public HuffmanTree(String newString) {
        myString = newString;

        freqArray = new int[ENCODING_TABLE_SIZE];
        fillFrequenceArray();

        huffmanTree = getHuffmanTree();

        encodingArray = new String[ENCODING_TABLE_SIZE];
        fillEncodingArray(huffmanTree.getRoot(), "", "");
    }

    //--------------------frequence array------------------------
    private void fillFrequenceArray() {
        for (int i = 0; i < myString.length(); i++) {
            freqArray[(int)myString.charAt(i)]++;
        }
    }

    public int[] getFrequenceArray() {
        return freqArray;
    }

    //------------------------huffman tree creation------------------
    private BinaryTree getHuffmanTree() {
        PriorityQueue pq = new PriorityQueue();
        //алгоритм описан выше
        for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
            if (freqArray[i] != 0) {//если символ существует в строке
                Node newNode = new Node((char) i, freqArray[i]);//то создать для него Node
                BinaryTree newTree = new BinaryTree(newNode);//а для Node создать BinaryTree
                pq.insert(newTree);//вставить в очередь
            }
        }

        while (true) {
            BinaryTree tree1 = pq.remove();//извлечь из очереди первое дерево.

            try {
                BinaryTree tree2 = pq.remove();//извлечь из очереди второе дерево

                Node newNode = new Node();//создать новый Node
                newNode.addChild(tree1.getRoot());//сделать его потомками два извлеченных дерева
                newNode.addChild(tree2.getRoot());

                pq.insert(new BinaryTree(newNode);
            } catch (IndexOutOfBoundsException e) {//осталось одно дерево в очереди
                return tree1;
            }
        }
    }

    public BinaryTree getTree() {
        return huffmanTree;
    }

    //-------------------encoding array------------------
    void fillEncodingArray(Node node, String codeBefore, String direction) {//заполнить кодировочную таблицу
        if (node.isLeaf()) {
            encodingArray[(int)node.getLetter()] = codeBefore + direction;
        } else {
            fillEncodingArray(node.getLeftChild(), codeBefore + direction, "0");
            fillEncodingArray(node.getRightChild(), codeBefore + direction, "1");
        }
    }

    String[] getEncodingArray() {
        return encodingArray;
    }

    public void displayEncodingArray() {//для отладки
        fillEncodingArray(huffmanTree.getRoot(), "", "");

        System.out.println("======================Encoding table====================");
        for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
            if (freqArray[i] != 0) {
                System.out.print((char)i + " ");
                System.out.println(encodingArray[i]);
            }
        }
        System.out.println("========================================================");
    }
    //-----------------------------------------------------
    String getOriginalString() {
        return myString;
    }
}

Sehlopha se nang le li-encode/decodes:

public class HuffmanOperator {
    private final byte ENCODING_TABLE_SIZE = 127;//длина таблицы
    private HuffmanTree mainHuffmanTree;//дерево Хаффмана (используется только для сжатия)
    private String myString;//исходное сообщение
    private int[] freqArray;//частотаная таблица
    private String[] encodingArray;//кодировочная таблица
    private double ratio;//коэффициент сжатия 


    public HuffmanOperator(HuffmanTree MainHuffmanTree) {//for compress
        this.mainHuffmanTree = MainHuffmanTree;

        myString = mainHuffmanTree.getOriginalString();

        encodingArray = mainHuffmanTree.getEncodingArray();

        freqArray = mainHuffmanTree.getFrequenceArray();
    }

    public HuffmanOperator() {}//for extract;

    //---------------------------------------compression-----------------------------------------------------------
    private String getCompressedString() {
        String compressed = "";
        String intermidiate = "";//промежуточная строка(без добавочных нулей)
        //System.out.println("=============================Compression=======================");
        //displayEncodingArray();
        for (int i = 0; i < myString.length(); i++) {
            intermidiate += encodingArray[myString.charAt(i)];
        }
        //Мы не можем писать бит в файл. Поэтому нужно сделать длину сообщения кратной 8=>
        //нужно добавить нули в конец(можно 1, нет разницы)
        byte counter = 0;//количество добавленных в конец нулей (байта в полне хватит: 0<=counter<8<127)
        for (int length = intermidiate.length(), delta = 8 - length % 8; 
        		counter < delta ; counter++) {//delta - количество добавленных нулей
            intermidiate += "0";
        }
        
        //склеить кол-во добавочных нулей в бинарном предаствлении и промежуточную строку 
        compressed = String.format("%8s", Integer.toBinaryString(counter & 0xff)).replace(" ", "0") + intermidiate;
        		
        //идеализированный коэффициент
        setCompressionRatio();
        //System.out.println("===============================================================");
        return compressed;
    }
    
    private void setCompressionRatio() {//посчитать идеализированный коэффициент 
        double sumA = 0, sumB = 0;//A-the original sum
        for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
            if (freqArray[i] != 0) {
                sumA += 8 * freqArray[i];
                sumB += encodingArray[i].length() * freqArray[i];
            }
        }
        ratio = sumA / sumB;
    }

    public byte[] getBytedMsg() {//final compression
        StringBuilder compressedString = new StringBuilder(getCompressedString());
        byte[] compressedBytes = new byte[compressedString.length() / 8];
        for (int i = 0; i < compressedBytes.length; i++) {
                compressedBytes[i] = (byte) Integer.parseInt(compressedString.substring(i * 8, (i + 1) * 8), 2);
        }
        return compressedBytes;
    }
    //---------------------------------------end of compression----------------------------------------------------------------
    //------------------------------------------------------------extract-----------------------------------------------------
    public String extract(String compressed, String[] newEncodingArray) {
        String decompressed = "";
        String current = "";
        String delta = "";
        encodingArray = newEncodingArray;
        
        //displayEncodingArray();
        //получить кол-во вставленных нулей
        for (int i = 0; i < 8; i++) 
        	delta += compressed.charAt(i);
        int ADDED_ZEROES = Integer.parseInt(delta, 2);
       
        for (int i = 8, l = compressed.length() - ADDED_ZEROES; i < l; i++) {
            //i = 8, т.к. первым байтом у нас идет кол-во вставленных нулей
            current += compressed.charAt(i);
            for (int j = 0; j < ENCODING_TABLE_SIZE; j++) {
                if (current.equals(encodingArray[j])) {//если совпало
                    decompressed += (char)j;//то добавляем элемент
                    current = "";//и обнуляем текущую строку
                }
            }
        }

        return decompressed;
    }

    public String getEncodingTable() {
        String enc = "";
    	for (int i = 0; i < encodingArray.length; i++) {
        	if (freqArray[i] != 0) 
        		enc += (char)i + encodingArray[i] + 'n';
        }
    	return enc;
    }

    public double getCompressionRatio() {
        return ratio;
    }


    public void displayEncodingArray() {//для отладки
        System.out.println("======================Encoding table====================");
        for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
            //if (freqArray[i] != 0) {
                System.out.print((char)i + " ");
                System.out.println(encodingArray[i]);
            //}
        }
        System.out.println("========================================================");
    }
    }

Sehlopha se thusang ho ngolla faele:

import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Closeable;

public class FileOutputHelper implements Closeable {
    private File outputFile;
    private FileOutputStream fileOutputStream;

    public FileOutputHelper(File file) throws FileNotFoundException {
        outputFile = file;
        fileOutputStream = new FileOutputStream(outputFile);
    }

    public void writeByte(byte msg) throws IOException {
        fileOutputStream.write(msg);
    }

    public void writeBytes(byte[] msg) throws IOException {
        fileOutputStream.write(msg);
    }

    public void writeString(String msg) {
    	try (PrintWriter pw = new PrintWriter(outputFile)) {
    		pw.write(msg);
    	} catch (FileNotFoundException e) {
    		System.out.println("Неверный путь, или такого файла не существует!");
    	}
    }

    @Override
    public void close() throws IOException {
        fileOutputStream.close();
    }

    public void finalize() throws IOException {
        close();
    }
}

Sehlopha se thusang ho bala ho tsoa faeleng:

import java.io.FileInputStream;
import java.io.EOFException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;

public class FileInputHelper implements Closeable {
	private FileInputStream fileInputStream;
	private BufferedReader fileBufferedReader;
	
	public FileInputHelper(File file) throws IOException {
		fileInputStream = new FileInputStream(file);
		fileBufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
	}
	
	
    public byte readByte() throws IOException {
    	int cur = fileInputStream.read();
    	if (cur == -1)//если закончился файл
    		throw new EOFException();
    	return (byte)cur;
    }
    
    public String readLine() throws IOException {
    	return fileBufferedReader.readLine();
    }
    
    @Override
    public void close() throws IOException{
    	fileInputStream.close();
    }
}

Hantle, le sehlopha se seholo:

import java.io.File;
import java.nio.charset.MalformedInputException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.util.List;
import java.io.EOFException;
public class Main {
	private static final byte ENCODING_TABLE_SIZE = 127;
	
    public static void main(String[] args) throws IOException {
        try {//указываем инструкцию с помощью аргументов командной строки
            if (args[0].equals("--compress") || args[0].equals("-c"))
                compress(args[1]);
            else if ((args[0].equals("--extract") || args[0].equals("-x"))
            		&& (args[2].equals("--table") || args[2].equals("-t"))) {
            	extract(args[1], args[3]);
            }
            else
                throw new IllegalArgumentException();
        } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException e) {
            System.out.println("Неверный формат ввода аргументов ");
            System.out.println("Читайте Readme.txt");
            e.printStackTrace();
        }
    }

	public static void compress(String stringPath) throws IOException {
        List<String> stringList;
        File inputFile = new File(stringPath);
        String s = "";
        File compressedFile, table;
        
        try {
            stringList = Files.readAllLines(Paths.get(inputFile.getAbsolutePath()));
        } catch (NoSuchFileException e) {
            System.out.println("Неверный путь, или такого файла не существует!");
            return;
        } catch (MalformedInputException e) {
        	System.out.println("Текущая кодировка файла не поддерживается");
        	return;
        }

        for (String item : stringList) {
            s += item;
            s += 'n';
        }

        HuffmanOperator operator = new HuffmanOperator(new HuffmanTree(s));

        compressedFile = new File(inputFile.getAbsolutePath() + ".cpr");
        compressedFile.createNewFile();
        try (FileOutputHelper fo = new FileOutputHelper(compressedFile)) {
        	fo.writeBytes(operator.getBytedMsg());
        }
        //create file with encoding table:
        
        table = new File(inputFile.getAbsolutePath() + ".table.txt");
        table.createNewFile();
        try (FileOutputHelper fo = new FileOutputHelper(table)) {
        	fo.writeString(operator.getEncodingTable());
        }
        
        System.out.println("Путь к сжатому файлу: " + compressedFile.getAbsolutePath());
        System.out.println("Путь к кодировочной таблице " + table.getAbsolutePath());
        System.out.println("Без таблицы файл будет невозможно извлечь!");
        
        double idealRatio = Math.round(operator.getCompressionRatio() * 100) / (double) 100;//идеализированный коэффициент
        double realRatio = Math.round((double) inputFile.length() 
        		/ ((double) compressedFile.length() + (double) table.length()) * 100) / (double)100;//настоящий коэффициент
        
        System.out.println("Идеализированный коэффициент сжатия равен " + idealRatio);
        System.out.println("Коэффициент сжатия с учетом кодировочной таблицы " + realRatio);
    }

    public static void extract(String filePath, String tablePath) throws FileNotFoundException, IOException {
        HuffmanOperator operator = new HuffmanOperator();
        File compressedFile = new File(filePath),
        	 tableFile = new File(tablePath),
        	 extractedFile = new File(filePath + ".xtr");
        String compressed = "";
        String[] encodingArray = new String[ENCODING_TABLE_SIZE];
        //read compressed file
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!check here:
        try (FileInputHelper fi = new FileInputHelper(compressedFile)) {
        	byte b;
        	while (true) {
        		b = fi.readByte();//method returns EOFException
        		compressed += String.format("%8s", Integer.toBinaryString(b & 0xff)).replace(" ", "0");
        	}
        } catch (EOFException e) {
        	
        }
        
        //--------------------
        
        //read encoding table:
        try (FileInputHelper fi = new FileInputHelper(tableFile)) {
        	fi.readLine();//skip first empty string
        	encodingArray[(byte)'n'] = fi.readLine();//read code for 'n'
        	while (true) {
        		String s = fi.readLine();
        		if (s == null)
        			throw new EOFException();
        		encodingArray[(byte)s.charAt(0)] = s.substring(1, s.length());        		
        	}
        } catch (EOFException ignore) {}
        
        extractedFile.createNewFile();
        //extract:
		try (FileOutputHelper fo = new FileOutputHelper(extractedFile)) {
			fo.writeString(operator.extract(compressed, encodingArray));
		}
		
		System.out.println("Путь к распакованному файлу " + extractedFile.getAbsolutePath());
    }
}

U tla tlameha ho ngola faele ka litaelo tsa readme.txt ka bouena 🙂

fihlela qeto e

Kea kholoa ke phetho seo ke neng ke batla ho se bua. Haeba u na le seo u ka se buang mabapi le ho hloka bokhoni ba ka ba ntlafatso ea khoutu, algorithm, ka kakaretso, ts'ebetso efe kapa efe, joale ikutloe u lokolohile ho ngola. Haeba ke so hlalose ho hong, ka kopo ngola hape. Ke kopa ho utloa ho tsoa ho uena maikutlong!

PES

E, e, ke ntse ke le mona, hobane ha kea lebala ka coefficient. Bakeng sa khoele ea s1, tafole ea khouto e boima ba li-byte tse 48 - ho feta faele ea pele, 'me ha baa ka ba lebala ka li-zero tse eketsehileng (palo ea li-zero ke 7) => tekanyo ea compression e tla ba ka tlaase ho e le' ngoe: 176 /(65 + 48*8 + 7) = 0.38. Haeba u boetse u hlokometse sena, joale feela eseng sefahlehong u se u qetile. Ee, ts'ebetsong ena e ke ke ea sebetsa hantle haholo bakeng sa lifaele tse nyane. Empa ho etsahala'ng ka lifaele tse kholo? Boholo ba lifaele bo boholo ho feta boholo ba tafole ea khouto. Mona ke moo algorithm e sebetsang ka moo e lokelang! Ka mohlala, bakeng sa Monologue ea Faust setsi sa polokelo ea lintho tsa khale se fana ka coefficient ea sebele (e sa tsitsang) e lekanang le 1.46 - hoo e batlang e le nako e le 'ngoe le halofo! E, faele e ne e lokela ho ba ka Senyesemane.

Source: www.habr.com

Eketsa ka tlhaloso