Oppgave 1
public static void dekomprimer(String fraUrl, String tilFil) throws IOException { BitInputStream inn = new BitInputStream((new URL(fraUrl)).openStream()); // åpner filen int k = inn.readBits(3); // antall biter i lengdene int[] lengder = new int[256]; // 256 mulige tegn for (int i = 0; i < lengder.length; i++) { if (inn.readBit() == 1) { lengder[i] = inn.readBits(k); } } int vaktpost = Tabell.maks(lengder); // tegnet med størst lengde int s = inn.readBits(5); // antall siffer i vaktpostens frekvens int vaktpostfrekvens = inn.readBits(s) + 1; int n = lengder[vaktpost]; // lengden til vaktposten int[] blader = new int[n + 1]; // n er nederste nivå for (int lengde : lengder) { if (lengde > 0) { blader[lengde]++; // finner antallet på hvert nivå } } int[] bitkoder = finnBitkoder(lengder); // finner bitkodene int m = (n + 1) / 2; // det midterste nivået i treet byte[] tegntabell = new byte[1 << m]; // en byte-tabell int[] høyder = treHøyde(blader, m); // de indre nodene på nivå m int grense = høyder.length; // skiller indre noder og blader for (int i = 0; i < grense; i++) { tegntabell[i] = (byte) høyder[i]; // høydene først i tegntabellen } int[] tilbake = new int[lengder.length]; // for tilbakelegging byte[][] tegntabeller = new byte[grense][]; // en to-dimensjonal tabell for (int i = 0; i < grense; i++) { tegntabeller[i] = new byte[1 << høyder[i]]; // størrelse 1 << høyder[i] } for (int i = 0; i < lengder.length; i++) // går gjennom alle lengdene { int lengde = lengder[i]; // hjelpevariabel if (lengde > 0) // tegnet i skal være med { if (lengde <= m) // den store tabellen { int d = m - lengde; // lengdeforskjellen tilbake[i] = d; // antall tilbake int fra = bitkoder[i] << d; // starten på tegn nr. i int til = fra + (1 << d); // slutten på tegn nr. i for (int j = fra; j < til; j++) { tegntabell[j] = (byte) i; // fyller ut } } else // de små tabellene { int kode = bitkoder[i]; // bitkoden til tegnet med i som asciiverdi int d1 = lengde - m; // differensen mellom lengde og m int kode1 = kode >> d1; // de m første bitene i kode int kode2 = kode & ((1 << d1) - 1); // de d1 siste bitene i kode byte[] b = tegntabeller[kode1]; // finner rett tabell int d2 = tegntabell[kode1] - d1; // differensen mellom høyden og k tilbake[i] = d2; // antall tilbake int fra = kode2 << d2; // starten på tegn i int til = fra + (1 << d2); // slutten på tegn i for (int j = fra; j < til; j++) { b[j] = (byte) i; // fyller ut } } } } BitOutputStream ut = new BitOutputStream(tilFil); // for utskrift int frekvens = 0; // forekomster av vaktposttegnet for (;;) { int lest = inn.readBits(m); // leser m biter int tall = tegntabell[lest] & 255; // slår opp i tegntabellen if (lest < grense) // lest gir en indre node { byte[] b = tegntabeller[lest]; // finner rett tabell lest = inn.readBits(tall); // leser flere biter tall = b[lest] & 255; // slår opp i tabellen } // tall er nå ascii-verdien til et tegn if (tall == vaktpost) { if (++frekvens == vaktpostfrekvens) { break; } } ut.write(tall); // skriver ut tegnet inn.unreadBits(tilbake[tall]); // legger biter tilbake } ut.close(); // lukker ut-filen inn.close(); }