import java.util.HashMap; import java.util.*; import java.nio.ByteBuffer; import java.util.Stack; import java.nio.file.Files; import java.nio.file.Path; public class Komprimierung { public static byte[] nullCharBytes = {(byte)0xFF,(byte)0xFF}; public static void test(String text) { Map zahlen = Zählen.countEachLetter(text); Node wurzel = Node.erstellen(zahlen); System.out.println(); System.out.println("Pre-Order Baum:"); printBaum(wurzel); System.out.println(); System.out.println("Anzahl der Zeichen:"); Zählen.printZahl(zahlen); System.out.println(); System.out.println("Binärcode der Zeichen:"); codes(text); System.out.println(); decodierungBaum(codierung(text,wurzel), wurzel); System.out.println(binärString_to_character(character_to_binärString(null))); System.out.println(binärString_to_character(character_to_binärString('b'))); System.out.println(binärString_to_character(character_to_binärString('c'))); System.out.println(binärString_to_character(character_to_binärString('d'))); System.out.println(binärString_to_character(character_to_binärString('e'))); System.out.println(binärString_to_character(character_to_binärString('f'))); System.out.println(binärString_to_character(character_to_binärString('g'))); System.out.println(binärString_to_character(character_to_binärString('h'))); binärString_to_baum(baum_to_binärString(wurzel)); printBaum(wurzel); } public static void test2() { Map zahlen = Zählen.countEachLetter("aaaabbc"); Node wurzel = Node.erstellen(zahlen); printBaum(wurzel); HashMap codes = new HashMap(); if(wurzel.getLeft() == null && wurzel.getRight() == null) { codes.put(wurzel.getBuchstabe(), "0"); } else { generieren(codes,wurzel,""); } for (var entry : codes.entrySet()) { System.out.println("->" + entry.getKey() + ", Code: " + entry.getValue()); } printBaum(binärString_to_baum(baum_to_binärString(wurzel))); } public static void test3() { System.out.println(decodierungInlkBaum(codierungInklBaum("aaaabbc"))); } public static void printBaum(Node baum) //gibt den Baum rekurssiv in pre-order aus { if(baum == null)return; System.out.println("Buchstabe: " + baum.getBuchstabe() + ", Anzahl: " + baum.getAnzahl()); printBaum(baum.getLeft()); //ruft die Methode rekuirsiv auf printBaum(baum.getRight()); } public static void codes(String text) //erstellt die codes für jeden einzelnen Buchstaben { Node wurzel = Node.erstellen(Zählen.countEachLetter(text)); //erstellt den Baum mithilfe der Node Klasse HashMap codes = new HashMap(); //erstellt eine leere Hashmap if(wurzel.getLeft() == null && wurzel.getRight() == null) //überprüft es ob der Baum mehr als ein zeichen lang ist { codes.put(wurzel.getBuchstabe(), "0"); } else //nutzt generieren um die codes zu generieren { generieren(codes,wurzel,""); } for (var entry : codes.entrySet()) //printet alle codes für das jeweiliege Zeichen { System.out.println("->" + entry.getKey() + ", Code: " + entry.getValue()); } } //methode zum generieren der codes für jeden einzelnen Buchstaben public static void generieren(HashMap codes, Node node, String code) { if(node == null)return; //abbruch Bedienung if(node.getLeft() == null && node.getRight() == null) //überprüft ob das Node ein "Blatt" ist { codes.put(node.getBuchstabe(), code); //wenn ja, gibt es den Buchstaben und den jeweiliegen code zurück return; } generieren(codes, node.getLeft(), code + "0"); //generiert rekursiv den code für die Äste generieren(codes, node.getRight(), code + "1"); } //generiert die Huffman-Codierung public static String codierung(String text, Node wurzel) { HashMap codes = new HashMap(); //erstellt eine leere Hashmap if(wurzel.getLeft() == null && wurzel.getRight() == null) //überprüft es ob der Baum mehr als ein zeichen lang ist { codes.put(wurzel.getBuchstabe(), "0"); } else //nutzt generieren um die codes zu generieren { generieren(codes,wurzel,""); } String code = ""; //erstellt leere Variable for (int i=0; i zahlen = Zählen.countEachLetter(text); Node baum = Node.erstellen(zahlen); //erstellt Baum String codierterBaum = baum_to_binärString(baum); //wandelt den Baum in Daten um, mit dem die Baumstruktur geladen werden kann String codierterText = codierung(text,baum); //speichert den codierten Text int textErstIndex = codierterBaum.length() + 32; //speichert den ersten Index der Text codierung String codiertertextErstIndex = Int_to_binärString(textErstIndex); //wandelt den textErstIndex in Binär um return codiertertextErstIndex + codierterBaum + codierterText; } //decodiert Buchstaben und speichert den Baum public static String decodierungInlkBaum(String code) { String codierterTextErstIndex = code.substring(0,32); //holt binärcode vom TextErstIndex int textErstIndex = binärString_to_int(codierterTextErstIndex); //wandelt codierterTextErstIndex in eine Integer String codierterBaum = code.substring(32, textErstIndex); Node decodierterBaum = binärString_to_baum(codierterBaum); String codierterText = code.substring(textErstIndex, code.length()); String decodierterText = decodierungBaum(codierterText,decodierterBaum); //decodiert den Text mit dem Baum return decodierterText; } //decodiert den Baum public static String decodierungBaum(String code,Node baum) { Node current = baum; String decoded = ""; boolean hatNurEinBuchstabenart = current.getRight() == null && current.getLeft() == null; if(hatNurEinBuchstabenart) //nimmt den einen Buchstabe und fügt ihn für n mal ein { for(int i=0;i8"); return null; } byte result = 0; for(byte i=0 ;i<8;i++) //geht den binärString durch und wandelt ihn in byte um { if(binärString.charAt(7-i) == '1')result|=1<>(7-i))&1)==1; //schaut ob der 7-i ste bit 1 ist result+= bit?'1': '0'; //falls bit wert 1 hat addiert es 1 zu dem string, wenn nicht dann addiertes es 0 } return result; } public static String character_to_binärString (Character c) { byte[] b = nullCharBytes; if(c != null) //wandelt character in "byte" { var byteBuffer = ByteBuffer.allocate(2); byteBuffer.putChar(c); b = byteBuffer.array(); } String result = ""; for(int i=0;i äste = new Stack(); //erstellt ein leeres Stack for(int i=0;i32"); return null; } int result = 0; for(int i=0 ;i<32;i++) //geht den binärString durch und wandelt ihn int um { if(binärString.charAt(31-i) == '1')result|=1<>(31-i))&1)==1; result+= bit?'1': '0'; //falls bit wert 1 hat addiert es 1 zu dem string, wenn nicht dann addiertes es 0 } return result; } //komprimiert Datei public static void compressFile (String source, String target ) { Path sourcePath = Path.of(source); Path targetPath = Path.of(target); if(Files.exists(sourcePath) == false) //überprüft ob im Dateipfad eine Datei hinterlegt ist { System.out.println("Datei nicht gefunden"); return; } String text; try { text = Files.readString(sourcePath); } catch(Exception error) //gibt error aus falls einer auftrit { System.out.println(error); return; } String compressedText = codierungInklBaum(text); try { Files.writeString(targetPath, compressedText); } catch(Exception error) { System.out.println(error); return; } } //liest die Datei public static void readFile(String file) { Path path = Path.of(file); if(Files.exists(path) == false) { System.out.println("Datei nicht gefunden"); return; } String compressedText; try { compressedText = Files.readString(path); } catch(Exception error) { System.out.println(error); return; } String text = decodierungInlkBaum(compressedText); System.out.println(file+": " + text); } }