用Java实现LZ78算法
我必须实现LZ78的编码器和解码器,以使.txt压缩,然后,使.txt解压缩 为此,我已经制作了编码器,文本输出编码如下:用Java实现LZ78算法,java,encoding,dictionary,decoding,Java,Encoding,Dictionary,Decoding,我必须实现LZ78的编码器和解码器,以使.txt压缩,然后,使.txt解压缩 为此,我已经制作了编码器,文本输出编码如下: Text: "I have to improve my english" Coded: "0I0 0h0a0v0e2t0o2i0m0p0r..." LZ78使用字典,字符串中的数字表示长字典条目的索引,如果字母不在字典中,则为0 问题是:如果文本字符串是数字链,如何区分索引的数字和文本字符串的数字 Text: "56786263...1234" <- the las
Text: "I have to improve my english"
Coded: "0I0 0h0a0v0e2t0o2i0m0p0r..."
LZ78使用字典,字符串中的数字表示长字典条目的索引,如果字母不在字典中,则为0
问题是:如果文本字符串是数字链,如何区分索引的数字和文本字符串的数字
Text: "56786263...1234" <- the last entry can be ((index 12 concat'3')concat index 4) instead of (index 123 concat '4')
Coded: "050607082223...'randomnumber'4"
Dictionary: (List<String>)
...
123: 'randomnumber' <- this is saved as a string
...
Text:“56786263…1234”注意:我假设这是家庭作业。如果不是,那么您应该对位(而不是字符)进行操作,并实现而不是
字典索引的长度取决于字典的总大小。虽然只有9个条目,但只能使用1个字符。一旦字典中有10个条目,您就需要使用2个字符作为所有条目的索引
请注意,解码器在处理流时会知道看到了多少词典条目,因此不需要单独存储词典的大小,只需逐渐增加用于存储索引的字符数即可。也就是说,一旦您存储了第10个字典条目,您就开始为将来的所有索引使用2个字符。完成第100个字典条目后,使用3个字符,以此类推
编辑:有一个分步示例,显示在解码阶段重建的词典。虽然链接描述了LZW(而不是LZ78),但想法是一样的:在解码时需要重建整个词典,并且不能从编码步骤重用词典(例如,考虑解码器和编码器可能位于不同的计算机上的情况->词典不通过网络发送。)一个“条目”应该是固定格式的记录。例如,2个字节用于字典索引(i
),2个字节用于字符串长度(n
),然后n
字节之后就是字符串。我不确定你的输出应该是字符串,或者应该使用读取器,或者输入压缩算法通常处理二进制数据,而不是文本。你不能假设编码器和解码器都知道字典。相反,您应该在每次编码和解码时构建字典。如果这样做,就不需要分隔符,因为索引的长度将始终是diccionario.size(),因此要澄清的是:您当前确实在编码时创建了词典,所以这没关系。但是,您需要以解码时相同的方式重新创建字典。在编目
开始时,字典diccionario
应为空,在解编目
开始时,字典应为空。然后,如您所见,数字code.size()
的长度应始终为diccionario.size()
。请参阅我添加的链接了解更多信息。“解码器和编码器可能位于不同计算机上的情况”这是问题的背景。但真正的问题不是解码,而是从文本缓冲区生成一个字典来生成消息,并实现某种方法来避免将索引号与字符号混淆,例如:。。。字典条目10=“456”。。。字典条目100=“jfas”。。。有123个字典条目(示例)文本要解码=“…0A101004…”现在,我有两种可能:-读取索引10并添加字符“0”-读取索引100并添加字符“1”-我无法读取1001,因为大小如何区分。这是因为您读取的字符数与字典的当前大小相同。在您的示例中,字典的大小为123,因此您可以读取索引100。但关键的一点是,在编码/解码开始时,字典的大小应该为0。然后在正文的中间,当你添加了14个元素时,字典的大小为14:所以你总是读2个字符作为索引。你这样做直到你的字典大小达到99,然后你总是读3个字符作为索引。你不需要分隔符。我实现了你说的,但是编码文本比原始文本大。无论如何,谢谢你的帮助。如果我找到解决方案,我会在这里发布
BufferedReader bufR = new BufferedReader(new FileReader(codedText));
BufferedWriter bufW = new BufferedWriter(new FileWriter(decodedText));
List<Character> list = new ArrayList<Character>();
int i=0;
int aux=bufR.read();
while(aux!=-1) {
list.add((char)aux);
i++;
aux=bufR.read();
}
System.out.println(list);
public class LZ78 {
List<String> diccionario;
public LZ78() {
diccionario = new ArrayList<String>();
diccionario.add(null);
}
public List<Character> codificar(List<Integer> listaNumeros){
String codif="";
List<Character> listaC =new ArrayList<Character>();
String letra="";
boolean brea=false;
int posicion=0;
for(int i=0;i<=listaNumeros.size()+1;i++){
int num=listaNumeros.get(i);
letra+=(char)num;
if(!diccionario.contains(letra)){
diccionario.add(letra);
codif+=0;
listaC.add('0');
codif+=letra;
char paso=letra.charAt(0);
listaC.add(paso);
letra="";
}else{
while(diccionario.contains(letra)){
i++;
if(i>=listaNumeros.size()){
brea=true;
if(!diccionario.contains(letra)){
listaC.add('0');
char paso2=letra.charAt(0);
listaC.add(paso2);
}else{
int index=diccionario.indexOf(letra);
String paso3=""+index;
for (int j = 0; j < paso3.length(); j++) {
listaC.add(paso3.charAt(j));
}
}
System.out.println("BREAK!");
break;
}
posicion=diccionario.indexOf(letra);
num=listaNumeros.get(i);
letra+=(char)num;
}
if(brea){
break;
}
i++;
diccionario.add(letra);
letra=""+letra.charAt(letra.length()-1);
codif+=posicion;
String numero=""+posicion;
for (int j = 0; j < numero.length(); j++) {
listaC.add(numero.charAt(j));
}
codif+=letra;
char paso=letra.charAt(0);
listaC.add(paso);
letra="";
i--;
}
}
System.out.println(codif);
return listaC;
}
//public void decodificar(List<Integer>)
public void codificacion(File textoPlano, File textoPlanoCodificado)
throws IOException {
BufferedReader bufLectura = new BufferedReader(new FileReader(
textoPlano));
BufferedWriter bufEscritura = new BufferedWriter(new FileWriter(
textoPlanoCodificado));
List<Integer> list = new ArrayList<Integer>();
int i=0;
int cosa=bufLectura.read();
while(cosa!=-1) {
list.add(cosa);
i++;
cosa=bufLectura.read();
}
List<Character> code=codificar(list);
char[] codigo=new char[code.size()];
for (int j = 0; j < code.size(); j++) {
//System.out.print(j+":'"+code.get(j)+"' ");
codigo[j]=code.get(j);
bufEscritura.write(codigo[j]);
}
System.out.println("FIN codificacion");
bufEscritura.close();
}
public void decodificacion(File textoC, File textoD) throws IOException{
BufferedReader bufLectura = new BufferedReader(new FileReader(textoC));
BufferedWriter bufEscritura = new BufferedWriter(new FileWriter(textoD));
List<Character> list = new ArrayList<Character>();
int i=0;
int cosa=bufLectura.read();
while(cosa!=-1) {
list.add((char)cosa);
i++;
cosa=bufLectura.read();
}
System.out.println(list);
//List<Integer> list2 =decodificar(list);
/*
List<Character> code=codificar(list);
char[] codigo=new char[code.size()];
for (int j = 0; j < code.size()-1; j++) {
codigo[j]=code.get(j);
bufEscritura.write(codigo[j]);
}
System.out.println("FIN codificacion");
bufEscritura.close();
*/
}
public static void main(String[] args) throws IOException {
LZ78 lz78 = new LZ78();
File textoPlano, textoPlanoCodificado, textoPlanoDecodificado;
textoPlano = new File("C:/pruebas/T.txt");
textoPlanoCodificado = new File("C:/pruebas/TOut.txt");
textoPlanoDecodificado = new File("C:/pruebas/TDecOut.txt");
lz78.codificacion(textoPlano, textoPlanoCodificado);
lz78.decodificacion(textoPlanoCodificado, textoPlanoDecodificado);
/*
* textoPlano = new File("C:/pruebas/MobyDick.txt");
* textoPlanoCodificado = new File("C:/pruebas/MobyDickOut.txt");
* textoPlanoDecodificado = new File("C:/pruebas/MobyDickDecOut.txt");
* lz78.codificacion(textoPlano, textoPlanoCodificado);
* lz78.decodificacion(textoPlanoCodificado, textoPlanoDecodificado);
*
* textoPlano = new File("C:/pruebas/Quixote.txt"); textoPlanoCodificado
* = new File("C:/pruebas/QuixoteOut.txt"); textoPlanoDecodificado = new
* File("C:/pruebas/QuixoteDecOut.txt"); lz78.codificacion(textoPlano,
* textoPlanoCodificado); lz78.decodificacion(textoPlanoCodificado,
* textoPlanoDecodificado);
*/
}