Konpresyon done lè l sèvi avèk algorithm Huffman

Antre

Nan atik sa a mwen pral pale sou pi popilè algorithm Huffman, osi byen ke aplikasyon li nan konpresyon done.

Kòm yon rezilta, nou pral ekri yon achiv senp. Sa a te deja diskite atik sou Habré, men san aplikasyon pratik. Materyèl teyorik pòs aktyèl la pran nan leson enfòmatik lekòl la ak liv Robert Laforet "Data Structures and Algorithms in Java". Se konsa, tout bagay koupe!

Kèk panse

Nan yon dosye tèks regilye, yon karaktè kode ak 8 bits (ASCII kodaj) oswa 16 (kodaj Unicode). Apre sa, nou pral konsidere kodaj ASCII la. Pa egzanp, pran liy s1 = "SUSIE DI LI FASIL". Gen yon total de 22 karaktè nan liy lan, natirèlman, ki gen ladan espas ak karaktè nan liy nouvo - 'n'. Fichye ki gen liy sa a pral peze 22 * ​​8 = 176 bit. Kesyon an rive imedyatman: èske li rasyonèl pou itilize tout 8 bits pou kode 1 karaktè? Nou pa sèvi ak tout karaktè ASCII. Menmsi yo te fè sa, li ta pi rasyonèl pou lèt ki pi komen an - S - yo bay kòd ki pi kout posib, epi pou lèt ki pi rar la - T (oswa U, oswa 'n') - yo bay yon kòd ki pi long. Sa a se sa algorithm Huffman a konsiste de: li nesesè jwenn opsyon an kodaj pi bon nan ki dosye a pral gen pwa a minimòm. Li se byen nòmal ke longè kòd yo pral diferan pou senbòl diferan - sa a se sa ki algorithm la baze sou.

Kodaj

Poukisa ou pa bay karaktè 'S' yon kòd, pou egzanp, 1 ti jan long: 0 oswa 1. Kite li dwe 1. Lè sa a, dezyèm karaktè ki pi komen - ' ' (espas) - bay 0. Imajine ou te kòmanse dekode mesaj ou a - fisèl la kode s1 - epi ou wè ke kòd la kòmanse ak 1. Se konsa, ki sa ou fè: sa a se karaktè S la, oswa se kèk lòt karaktè, pou egzanp A? Se poutèt sa, yon règ enpòtan rive:

Ni kòd pa ta dwe yon prefiks yon lòt

Règ sa a se kle nan algorithm la. Se poutèt sa, kreye yon kòd kòmanse ak yon tablo frekans, ki endike frekans (kantite evènman) chak senbòl:

Konpresyon done lè l sèvi avèk algorithm Huffman Karaktè ki gen plis ensidan yo ta dwe kode pi piti posib kantite bit. Mwen pral bay yon egzanp youn nan tablo kòd posib yo:

Konpresyon done lè l sèvi avèk algorithm Huffman Se konsa, mesaj la kode ap gade tankou sa a:

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

Mwen separe kòd chak karaktè ak yon espas. Sa a pa pral rive nan yon dosye vrèman konprese!
Kesyon an rive: ki jan jèn sa a te fè vini ak kòd la pou kreye yon tab nan kòd? Sa a pral diskite anba a.

Konstwi yon pye bwa Huffman

Sa a se kote pye bwa rechèch binè vin pote sekou. Pa enkyete w, ou p ap bezwen rechèch, mete, oswa efase metòd isit la. Men estrikti pye bwa a nan 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;
    }
    ...
}

Sa a se pa kòd konplè a, kòd konplè a pral anba a.

Men algorithm pou konstwi pye bwa a:

  1. Kreye yon objè Node pou chak karaktè nan mesaj la (liy s1). Nan ka nou an pral gen 9 nœuds (objè nœuds). Chak ne konsiste de de jaden done: senbòl ak frekans
  2. Kreye yon objè Tree (BinaryTree) pou chak Node. Ne a vin rasin pye bwa a.
  3. Mete pye bwa sa yo nan keu priyorite a. Pi ba frekans lan, pi wo priyorite a. Kidonk, lè ekstrè, dervo a ak frekans ki pi ba a toujou chwazi.

Apre sa, ou bezwen fè sa ki annapre yo yon fason siklik:

  1. Retire de pye bwa nan keu priyorite a epi fè yo pitit nouvo ne (ne ki fèk kreye san lèt la). Frekans nouvo ne egal a sòm frekans de pyebwa desandan yo.
  2. Pou ne sa a, kreye yon pye bwa ak rasin nan ne sa a. Mete pye bwa sa a tounen nan keu priyorite a. (Depi pye bwa a gen yon nouvo frekans, li pral gen plis chans parèt nan yon nouvo kote nan keu la)
  3. Kontinye etap 1 ak 2 jiskaske gen yon sèl pye bwa ki rete nan keu a - pye bwa Huffman.

Konsidere algorithm sa a sou liy s1:

Konpresyon done lè l sèvi avèk algorithm Huffman

Isit la senbòl "lf" (linefeed) vle di yon nouvo liy, "sp" (espas) se yon espas.

Kisa kap vini an?

Nou te gen yon pye bwa Huffman. OK. Ak kisa pou fè ak li? Yo pa pral menm pran li gratis.Epi lè sa a, ou bezwen trase tout chemen posib soti nan rasin nan fèy yo nan pye bwa a. Ann dakò pou nou endike yon kwen 0 si li mennen nan pitit gòch la ak 1 si li mennen nan youn nan dwa. Fè egzateman pale, nan notasyon sa a, kòd yon senbòl se chemen ki soti nan rasin pye bwa a rive nan fèy ki gen senbòl sa a.

Konpresyon done lè l sèvi avèk algorithm Huffman

Sa a se ki jan tab la nan kòd yo te tounen soti. Remake byen ke si nou konsidere tablo sa a, nou ka konkli sou "pwa" chak senbòl - sa a se longè kòd li yo. Lè sa a, nan fòm konprese, dosye orijinal la pral peze: 2 * 3 + 2 * 4 + 3 * 3 + 6 * 2 + 1 * 4 + 1 * 5 + 2 * 4 + 4 * 2 + 1 * 5 = 65 bits . Okòmansman, li te peze 176 bits. Kontinwe, nou redwi li pa otan ke 176/65 = 2.7 fwa! Men, sa a se yon utopi. Yon koyefisyan sa a pa fasil pou jwenn. Poukisa? Sa a pral diskite yon ti kras pita.

Dekodaj

Oke, petèt bagay ki pi senp ki rete a se dekodaj. Mwen panse ke anpil nan nou te devine ke nou pa ka tou senpleman kreye yon dosye konprese san okenn allusion sou ki jan li te kode - nou pa yo pral kapab dekode li! Wi, wi, li te difisil pou mwen reyalize sa a, men mwen pral oblije kreye yon dosye tèks table.txt ak yon tab konpresyon:

01110
 00
A010
E1111
I110
S10
T0110
U01111
Y1110

Tablo antre nan fòm 'senbòl' 'kòd karaktè'. Poukisa 01110 san yon senbòl? An reyalite, li se ak yon senbòl, se jis ke zouti yo java mwen itilize lè pwodiksyon nan yon dosye, karaktè nan Newline - 'n' - konvèti nan yon Newline (kèlkeswa jan estipid li ka son). Se poutèt sa, liy vid ki anlè a se karaktè pou kòd 01110. Pou kòd 00, karaktè a se yon espas nan kòmansman liy lan. Mwen pral di touswit ke pou koyefisyan Khan nou an, metòd sa a nan estoke yon tab ka reklame ke li pi irasyonèl la. Men, li fasil pou konprann ak aplike. Mwen pral kontan tande rekòmandasyon ou yo nan kòmantè yo konsènan optimize.

Èske w gen tab sa a fè li trè fasil dekode. Se pou nou sonje ki règ nou te swiv lè nou te kreye kodaj la:

Ni kòd pa ta dwe yon prefiks yon lòt

Sa a se kote li jwe yon wòl fasilite. Nou li sekans ti jan pa ti jan epi, le pli vit ke fisèl ki kapab lakòz d la, ki fòme ak ti bit yo li, matche ak kodaj ki koresponn ak karaktè karaktè a, nou imedyatman konnen ke karaktè karaktè a (e sèlman li!) te kode. Apre sa, nou ekri karaktè nan liy lan dekode (liy la ki gen mesaj la dekode), reset liy d, ak Lè sa a, li dosye a kode.

Aplikasyon

Li lè pou imilye kòd mwen an epi ekri yon achiv. Ann rele li Compressor.

Rekomanse. Premye a tout, nou ekri klas la 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;
    }
}

Koulye a, pye bwa a:

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

Keu priyorite:

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

Klas ki kreye pye bwa Huffman la:

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

Klas ki genyen ki kode/dekode:

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

Yon klas ki fè li pi fasil pou ekri nan yon fichye:

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

Yon klas ki fè li pi fasil pou li nan yon dosye:

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

Oke, ak klas prensipal la:

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

Ou pral oblije ekri fichye readme.txt la tèt ou :)

Konklizyon

Mwen devine se tout sa mwen te vle di. Si ou gen anyen pou di sou enkonpetans mwen nan amelyore kòd la, algorithm, oswa nenpòt optimize an jeneral, Lè sa a, santi yo lib yo ekri. Si mwen pa eksplike anyen, tanpri ekri tou. Mwen ta renmen tande pale de ou nan kòmantè yo!

PS

Wi, wi, mwen toujou la, paske mwen pa bliye sou koyefisyan an. Pou fisèl s1, tab kodaj la peze 48 bytes - pi gwo pase fichye sous la, epi nou pa t bliye sou zewo adisyonèl yo (kantite zewo te ajoute yo se 7) => rapò konpresyon an pral mwens pase yon sèl: 176/ (65 + 48*8 + 7) = 0.38. Si ou remake tou sa a, Lè sa a, se pa sèlman figi ou ki gwo. Wi, aplikasyon sa a pral trè efikas pou ti fichye yo. Men, sa k ap pase gwo dosye? Gwosè dosye yo pi gwo pase gwosè tab kodaj la. Sa a se kote algorithm la ap travay jan li ta dwe! Pou egzanp, pou Monològ Faust la Achiv la pwodui yon koyefisyan reyèl (pa ideyalize) nan 1.46 - prèske yon fwa ak yon mwatye! Epi wi, dosye a te sipoze an Angle.

Sous: www.habr.com

Add nouvo kòmantè