Kudzvanywa kwedata neHuffman algorithm

kupinda

Muchikamu chino, ini ndichataura nezve inozivikanwa Huffman algorithm, pamwe nekushandiswa kwayo mukumanikidza data.

Nekuda kweizvozvo, isu tichanyora iri nyore archiver. Izvi zvatove nyaya yaHabré, asi pasina kushandiswa kunoshanda. Iyo theoretical zvinhu zveiyo post inotorwa kubva kuchikoro kombiyuta zvidzidzo zvesainzi uye bhuku raRobert Laforet "Data Structures uye Algorithms muJava". Saka, zvinhu zvose zviri pasi pekucheka!

Kufungisisa zvishoma

Mune yakajairika mameseji faira, mutsara mumwe wakavharirwa ne8 bits (ASCII encoding) kana 16 (Unicode encoding). Tevere, isu tichafunga iyo ASCII encoding. Semuenzaniso, tora tambo s1 = "SUSIE ANOTI ZVIRI NYORERE". Pakazara, kune mavara makumi maviri nemaviri mumutsara, hongu, kusanganisira nzvimbo uye mutsara mutsva - 'n'. Iyo faira ine mutsara uyu ichayera 22 * ​​22 = 8 bits. Mubvunzo unomuka pakarepo: zvine musoro here kushandisa ese 176 mabhiti encode 8 chimiro? Isu hatishandise ese ASCII mavara. Kunyangwe dai vanga varipo, zvingava zvine musoro kupa bhii rinowanzogara - S - kodhi ipfupi inokwanisika, uye yetsamba isingawanzo - T (kana U, kana 'n') - ipa iyo kodhi yechokwadi. Iyi ndiyo Huffman algorithm: iwe unofanirwa kutsvaga yakanakisa encoding sarudzo, umo iyo faira ichave ine huremu hushoma. Izvo zvakajairika kuti mavara akasiyana achave akasiyana kodhi kureba - iyi ndiyo hwaro hweiyo algorithm.

Coding

Wadii kupa chimiro 'S' kodhi, semuenzaniso, 1 bit kureba: 0 kana 1. Ngaive 1. Zvino wechipiri anonyanya kuitika - '' (nzvimbo) - tichapa 0. Fungidzira, watanga decode meseji yako - encoded tambo s1 - uye unoona kuti kodhi yacho inotanga na 1. Saka, zvekuita: ivara S, kana kuti humwe hunhu, hwakaita saA? Naizvozvo, mutemo unokosha unomuka:

Hapana kodhi inofanira kuva prefix yeimwe

Uyu mutemo ndiyo kiyi kune algorithm. Naizvozvo, kusikwa kwekodhi kunotanga netafura yefrequency, iyo inoratidza kuwanda (nhamba yezvinoitika) yechiratidzo chega chega:

Kudzvanywa kwedata neHuffman algorithm Mavara ane akanyanya kuitika anofanirwa kuvharirwa neashoma zvinogoneka nhamba yezvimedu. Ini ndichapa muenzaniso weimwe inobvira kodhi matafura:

Kudzvanywa kwedata neHuffman algorithm Saka iyo encoded meseji ichaita seizvi:

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

Ndakaparadzanisa kodhi yemunhu wega wega nenzvimbo. Izvi hazvizonyatso kuitika mune yakamanikidzwa faira!
Mubvunzo unomuka: uyu rookie akauya sei nekodhi nzira yekugadzira tafura yekodhi? Izvi zvichakurukurwa pasi apa.

Kuvaka Huffman Tree

Apa ndipo apo miti yekutsvaga yemabhinari inouya kuzonunura. Usanetseke, hauzodi kutsvaga, kuisa, nekudzima nzira pano. Heino chimiro chemuti mujava:

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;
    }
    ...
}

Iyi haisi iyo yakazara kodhi, iyo yakazara kodhi ichave pazasi.

Heino algorithm yekuvaka muti:

  1. Gadzira chinhu cheNode kune yega yega meseji (mutsara s1). Muchiitiko chedu, pachava ne9 nodes (Node zvinhu). Node imwe neimwe ine zvikamu zviviri zve data: chiratidzo uye frequency
  2. Gadzira chinhu cheMuti (BinaryTree) kune imwe neimwe yeNode node. Node inova mudzi wemuti.
  3. Isa miti iyi mumutsara wekutanga. Iyo yakaderera frequency, yakakwirira iyo yekutanga. Nokudaro, kana uchibvisa, muti une zvishoma zvishoma unogara wakasarudzwa.

Tevere, iwe unofanirwa kuita cyclically kuita zvinotevera:

  1. Dzora miti miviri kubva pamutsetse wekutanga uye uite vana venode itsva (node ​​ichangobva kugadzirwa isina tsamba). Kuwanda kwenodhi itsva kwakaenzana nehuwandu hwehuwandu hwemiti miviri inobereka.
  2. Kune iyi node, gadzira muti wakadzika midzi pane ino node. Pinza muti uyu zvakare mumutsara wekutanga. (Sezvo muti wacho une frequency nyowani, inogona kunge ichipinda munzvimbo nyowani mumutsara)
  3. Ramba nhanho 1 ne2 kusvika muti mumwe wasara mumutsara - muti weHuffman

Funga nezve iyi algorithm pamutsetse s1:

Kudzvanywa kwedata neHuffman algorithm

Pano chiratidzo "lf" (linefeed) chinoreva mutsara mutsva, "sp" (nzvimbo) inzvimbo.

Chii chinotevera?

Tine muti weHuffman. OK. Uye zvokuita nazvo? Havazvitore mahara.Uyezve, unofanira kutsvaga nzira dzese dzinobvira kubva pamudzi kusvika kumashizha emuti. Isu tinobvumirana kuisa mupendero 0 kana ichitungamira kumwana wekuruboshwe uye 1 kana ichitungamira kune kurudyi. Kunyatsotaura, mune izvi zvinyorwa, kodhi yehunhu ndiyo nzira kubva pamudzi wemuti kuenda pashizha rine chimiro chimwe chete ichi.

Kudzvanywa kwedata neHuffman algorithm

Saka, tafura yekodhi yakashanduka. Cherechedza kuti kana tikafunga tafura iyi, tinogona kugumisa nezve "kurema" kwemunhu mumwe nomumwe - iyi ndiyo urefu hwekodhi yayo. Zvadaro, mufomu yakamanikidzwa, iyo faira faira ichayera: 2 * 3 + 2 * 4 + 3 * 3 + 6 * 2 + 1 * 4 + 1 * 5 + 2 * 4 + 4 * 2 + 1 * 5 = 65 bits. . Pakutanga rairema 176 bits. Naizvozvo, takaidzikisa nekuwanda se176/65 = 2.7 nguva! Asi iyi iutopia. Chiyero chakadaro hachibviri kuwanikwa. Sei? Izvi zvichakurukurwa gare gare.

Decoding

Zvakanaka, pamwe chinhu chakareruka chasara ndechekunyora. Ini ndinofunga vazhinji venyu vakafungidzira kuti hazvigoneke kungogadzira faira rakadzvanywa pasina chero zano rekuti rakavharwa sei - isu hatizokwanisa kuitsanangura! Hongu, hongu, zvakandiomera kuti ndizive izvi, asi ndinofanira kugadzira tafura yefaira remavara.txt ine tafura yekumanikidza:

01110
 00
A010
E1111
I110
S10
T0110
U01111
Y1110

Tafura yekupinda muchimiro che'character'"character code". Sei 01110 isina chiratidzo? Muchokwadi, iyo ine chiratidzo, chete maturusi ejava andinoshandisa kana ndichiburitsa kune faira, iyo nyowani mutsara - 'n' - inoshandurwa kuita nyowani (zvisinei kuti inonzwika sei benzi). Nokudaro, mutsara usina chinhu pamusoro apa ndiwo mutsara wekodhi 01110. Kwekodhi 00, chimiro inzvimbo pakutanga kwemutsara. Ndinofanira kutaura ipapo ipapo kuti iyi nzira yekuchengetedza tafura inogona kuzviti ndiyo yakanyanya kusanzwisisika kune yedu khan coefficient. Asi zviri nyore kunzwisisa uye kushandisa. Ini ndichafara kunzwa kurudziro yako mune zvakataurwa nezve optimization.

Netafura iyi, zviri nyore kwazvo kudhirodha. Ngatirangarirei mutemo watakatungamirirwa nawo pakugadzira encoding:

Hapana kodhi inofanira kuva prefix yeimwe

Apa ndipo panoita basa rekufambisa. Isu tinoverenga zvishoma nezvishoma sequentially, uye nekukurumidza kana tambo inoguma d, ine mabhiti akaverengwa, inofananidzwa neiyo encoding inoenderana nehunhu, isu tinobva taziva kuti hunhu (uye chete!) Tevere, tinonyora hunhu kune decode tambo (tambo ine decoded meseji), gadzirisa d tambo, uye verenga encoded faira mberi.

Kutevedzera

Yave nguva yekunyadzisa kodhi yangu nekunyora dura. Ngatitii Compressor.

Tanga patsva. Chokutanga pane zvose, tinonyora kirasi yeNode:

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;
    }
}

Zvino muti:

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;
    }
}

Mutsara wezvakakosha:

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;//возвращаем удаленный элемент(элемент с наименьшей частотой)
    }
}

Kirasi inogadzira muti weHuffman:

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;
    }
}

Kirasi ine maencodes/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("========================================================");
    }
    }

Kirasi inofambisa kunyora kune faira:

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();
    }
}

Kirasi inofambisa kuverenga kubva mufaira:

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();
    }
}

Zvakanaka, uye kirasi huru:

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());
    }
}

Iwe uchafanirwa kunyora faira nereadme.txt mirairo iwe pachako 🙂

mhedziso

Ndofunga ndizvo chete zvandaida kutaura. Kana iwe uine chimwe chinhu chekutaura pamusoro pekusagona kwangu kwekuvandudza mukodhi, algorithm, kazhinji, chero optimization, saka inzwa wakasununguka kunyora. Kana ndisina kutsanangura chimwe chinhu, ndapota nyorawo. Ndinoda kunzwa kubva kwamuri mumashoko!

PS

Hongu, hongu, ndichiri pano, nekuti handina kukanganwa nezve coefficient. Kune iyo tambo s1, iyo encoding tafura inorema 48 bytes - zvakanyanya kupfuura faira rekutanga, uye havana kukanganwa nezve mamwe mazero (nhamba yezero yakawedzerwa i7) => iyo yekumanikidza reshiyo ichave isingasviki imwe: 176 /(65 + 48*8 + 7) = 0.38. Kana iwe wakacherechedzawo izvi, saka chete kwete muchiso iwe wapedza. Ehe, kuita uku kuchave kushoma zvakanyanya kune madiki mafaira. Asi chii chinoitika kumafaira makuru? Iwo masaizi efaira akakurisa kupfuura encoding table size. Apa ndipo panoshanda algorithm sezvainofanirwa! Somuenzaniso, nokuda Faust's monologue iyo archiver inopa chaiyo (isina idealized) coefficient yakaenzana ne1.46 - kanenge kamwechete nehafu! Uye hongu, faira yaifanirwa kunge iri muChirungu.

Source: www.habr.com

Voeg