import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;
public class LZW
{
private int dictionaryIndexToPrint = 0; //Befindet sich das Teilwort schon im Wörterbuch, wird hier der Index gespeichert
private boolean wasInDictionary = false; //Wird für die Funktion isAlreadyInCodeTable benötigt
public static String g_fileExtension = new String();
public void compress(File file)
{
if(file.exists() != true)
{
System.out.println("Datei existiert nicht, programm wird beendet");
return;
}
try{
File comFile = new File(newFileName(file)); //Die neue Datei anlegen
comFile.createNewFile();
//FileHeader erstellen
FileHeader fh = new FileHeader(comFile);
fh.writeHeader();
RandomAccessFile fileReader = new RandomAccessFile(file, "r");
RandomAccessFile fileWriter = new RandomAccessFile(comFile, "rw");
System.out.println("Die Originaldatei " + file.getName() + " hat eine groesse von " + fileReader.length() + " Bytes\n");
short gelesenesByte;
String puffer = new String();
short index = 256;
String[][] codeTable = new String[(int)fileReader.length()][2]; //Spalte zwei für den Index
//Codetabelle mit "" füllen
for(long i = 0; i < fileReader.length(); i++)
codeTable[(int)i][0] = "";
//LZW Tabelle
System.out.println("Lesen\tCodetabelle\tAusgabe\t\tPuffer");
for(long i = 0; i < fileReader.length(); i++)
{
gelesenesByte = (short)fileReader.read(); //Einlesen des nächsten zeichens
if(i == 0) //Im ersten durchgang wird noch nichts ins Wörterbuch geschrieben
{
puffer = Integer.toString(gelesenesByte); //sondern nur das gelesene zeichen in den puffer übernommen
System.out.printf("%5s %40s\n", String.valueOf(gelesenesByte), puffer);
continue;
}
//Befindet sich das Teilwort bestehen aus puffer + gelesenesByte schon in der Codetabelle
if(isAlreadyInCodeTable(codeTable, new String(puffer + Integer.toString(gelesenesByte)), i) == false)
{
//Es befindet sich noch nicht in der Codetabelle
codeTable[(int)i][0] = "" + puffer + gelesenesByte;
codeTable[(int)i][1] = Integer.toString(index);
//System.out.printf("%10s %10s\n", String.valueOf(codeTable[(int)i][0]), String.valueOf(codeTable[(int)i][1]));
index++;
//Den Puffer in die Datei schreiben
//for(int j = 0; i < puffer.length(); j++)
//fileWriter.write(puffer.charAt(j));
//Ausgabe für die Tabelle
if(wasInDictionary == false)
{
System.out.printf("%5s %13s %11s %14s\n", String.valueOf(gelesenesByte), puffer + String.valueOf(gelesenesByte), puffer, String.valueOf(gelesenesByte));
fileWriter.writeShort(Integer.parseInt(puffer));
}
else
{
System.out.printf("%5s %13s %11s %14s\n", String.valueOf(gelesenesByte), puffer + String.valueOf(gelesenesByte), dictionaryIndexToPrint, String.valueOf(gelesenesByte));
fileWriter.writeShort(dictionaryIndexToPrint);
}
puffer = Integer.toString(gelesenesByte);
wasInDictionary = false;
}
else
{
//Es befindet sich schon in der Codetabelle
puffer += gelesenesByte;
}
}
System.out.printf("EOF %42s", puffer);
fileWriter.writeShort(Short.parseShort(puffer));
System.out.println("\nDie komprimierte Datei hat eine groesse von " + fileWriter.length() + " Bytes");
fileReader.close();
fileWriter.close();
} catch(IOException e) {
}
}
private String newFileName(File file)
{
String s = file.getName(); // meinText.txt
String path = file.getAbsolutePath();
int indexPath = path.lastIndexOf(s);
path = path.substring(0, indexPath);
int index = s.lastIndexOf(".");
g_fileExtension = s.substring(index +1, s.length());//txt
s = s.substring(0, index) + ".mip"; //meinText.mip
path += s;
return path;
}
private boolean isAlreadyInCodeTable(String[][] ct, String s, long lCounter)
{
for(long i = 0; i < lCounter; i++)
{
if(ct[(int)i][0].equals(s))
{
dictionaryIndexToPrint = Integer.parseInt(ct[(int)i][1]);
wasInDictionary = true;
return true;
}
}
return false;
}
private String origFileName(File file)
{
//Über den Header die Originalendung herauslesen
FileHeader fh = new FileHeader(file);
String ext = new String(fh.readHeader());
String path = file.getAbsolutePath();
int index = path.lastIndexOf(".");
path = path.substring(0, index) + ext;
return path;
}
public void decompress(File file)
{
if(file.exists() != true)
{
System.out.println("Datei existiert nicht, programm wird beendet");
return;
}
try{
File decomFile = new File(origFileName(file)); //Die neue Datei anlegen
decomFile.createNewFile();
RandomAccessFile fileReader = new RandomAccessFile(file, "r");
RandomAccessFile fileWriter = new RandomAccessFile(decomFile, "rw");
//String sAusgabe = ""; //In diesem String soll die Ausgabe gespeichert werden, die eigl in der Originaldatei stand
short geleseneZweiByte;
String letztesWort = "";
String codeTable[][] = new String[(int)fileReader.length()][2]; //Zweite Spalte wieder für den Index
int index = 256;
//Codetabelle mit "" füllen
for(long i = 0; i < fileReader.length(); i++)
codeTable[(int)i][0] = "";
for(long i = 0; i < fileReader.length(); i++)
{
geleseneZweiByte = (short)fileReader.readUnsignedShort(); //Zwei Byte einlesen
if(i == 0) //Im ersten Durchgang wird noch nichts im Wörterbuch geprüft
{
//sAusgabe += String.format("%C", geleseneZweiByte);
fileWriter.writeBytes(String.format("%C", geleseneZweiByte));
letztesWort = Short.toString(geleseneZweiByte);
continue;
}
if(geleseneZweiByte <= 255) //Befindet sich in der ASCII Tabelle und nicht im Wörterbuch
{
//sAusgabe += String.format("%C", geleseneZweiByte);
fileWriter.writeBytes(String.format("%C", geleseneZweiByte));
//Befindet sich letztesWort + geleseneZweiByte in der CodeTabelle
if(isAlreadyInCodeTable(codeTable, new String(letztesWort + Short.toString(geleseneZweiByte)), i) == false)
{
//Befindet sich noch nicht in der Code Tabelle
codeTable[(int)i][0] = letztesWort + Short.toString(geleseneZweiByte);
codeTable[(int)i][1] = Integer.toString(index);
index++;
}
continue; //Verhindert die if() abfrage von > 255
}
if(geleseneZweiByte > 255)
{
//gesucht wird die Position von j, an der sich geleseneZwei Byte befindet
for(int j = 0; j < i; j++)
{
if(codeTable[j][1] == Short.toString(geleseneZweiByte))
{
//sAusgabe += codeTable[j][0];
fileWriter.writeBytes(codeTable[j][0]);
}
}
}
}
//Den Originaltext ausgeben
//System.out.println("Originaltext:\n" + sAusgabe);
} catch(IOException e) {
}
}