package com.anywhere;
import java.io.*;
/** 一个lzw 压缩算法的 编码 和译码 的实现程序
* 压缩一个已有文件(sourcefile)到目标文件(targetfile) ,然后读取压缩的码;
* 此程序采用12位压缩码,词典作多可以存储2^12个词条;
* 生成的压缩码 经过解压缩,可以恢复为原先文件;
*对文本文件的压缩率,大约为60%,尚不能支持中文的文件输入:)
* @author Lai Yongxuan 2003.3.12
* @version 1.0
*/
public class lzwCode
{
/**
@see Dictionary
*/
Dictionary dic=new Dictionary();
/**count1: the bytes of input file,count2:the bytes of output file
*/
int count1=0,count2=0;
/** the max number of the dictionary;
*this number can be add to the codebuf[] if
* the file has only odd words to be treated ;
*/
/** the input file : character file or coding file
*/
BufferedInputStream in;
/** the output file: character file or coding file
*/
BufferedOutputStream out;
final short END=4095;
/**the entry of the class,and check the arguments first
@param args array of string arguments
-c sourceFile [targetFile] 建立一个压缩文件
-d sourceFile [targetFile] 解压缩一个文件
@return No return value
@exception No ecceptions thrown
*/
public static void main(String []args)
{
if ( args.length<=1 || args.length>4 )
{
System.out.println("-c sourceFile [targetFile] [-dic] 建立一个压
缩文件\n");
System.out.println("-d sourceFile [targetFile] [-dic] 解压缩一个
文件\n");
}
else if(! ( args[0].equals(new String("-c") )||args[0].equals(new
String("-d") ) ) )
{
System.out.println("-c sourceFile [targetFile] 建立一个压缩文件\
n");
System.out.println("-d sourceFile [targetFile] 解压缩一个文件\n"
);
}
else if(args.length>=2)
{
lzwCode a=new lzwCode(args);
a.run(args);
}
return ;
}
/** the constuctor of the class of "lzwCode "
*@param args array of string arguments input at the main()
*
*
*/
public lzwCode(String []args)
{
try{
String f=new String();
in =new BufferedInputStream(
new FileInputStream(
new File(args[1])));
if(args.length==3 && !args[2].equals(new String("-dic")))
{
f=args[2];
}
else
{
int i=args[1].lastIndexOf(new String(".") );
f=args[1].substring(0,i)+((args[0].equals("-c")
)?".lzw":".dlzw");
}
out=new BufferedOutputStream(
new FileOutputStream(
new File(f)));
}//try
catch(FileNotFoundException e )
{
System.err.println(e);
return;
}
catch(IOException e )
{
System.err.println(e);
return;
}
}
/** the entry of the process;
@param Srring args[]: array of string arguments input at the main()
BufferedInputStream in: the input charstream file
BufferedOutputStream out:the output code stream file
* @return No return value
*/
public void run(String args[] )
{
if(args[0].equals(new String("-c")) )
{
code(in,out);
}
else
{
decode(in,out);
}
if(args[args.length-1].equals(new String("-dic") ))
System.out.println(dic.toString ());
}
/** input the charstream from a file,and output the code stream to anpther
file
* @param BufferedInputStream in: the input charstream file
BufferedOutputStream out:the output code stream file
* @return No return value
*
*/
public void code(BufferedInputStream in,BufferedOutputStream out)
{
System.out.println("coding...\n"+ ".......\n");
//a:the buffer byte read from the input file,then to be converted to
String
//buf: the codestream to store in the code file
//prefix :the pre_String of the dictory
// the indexbuf[] is the index of dictionary to be converted in
// the code file
//str: the current charecter of the character input Stream
byte a[]=new byte[1],buf[]=new byte[3];
String prefix="",cur="";
byte i=0;
short indexbuf[]=new short[2];
String str=null;
try{
short m=0;
while( (a[0]=(byte)in.read() ) != -1 )
{
cur=new String(a);// be converted
count1++; // the number of bytes of input file
str=prefix;
str=str.concat(cur);
m=(short)dic.indexOf(str);
if( m!=-1)//the prefix is in the dictionary,
{
prefix=str;
}
else//
{
if(i==0)//the first indexbuf,store in codebuf[]
{
indexbuf[0]=(short)dic.indexOf(prefix);
i=1;
}
else// now have 2 index number,then ouput to the code file
{
indexbuf[1]=(short)dic.indexOf(prefix);
zipOutput(out,indexbuf);
count2+=3;//3 bytes stored to the code file
i=0;
}
dic.add(str);
prefix=cur;
}//else
}//while
// System.out.println("i="+i);
if(i==(byte)1) //this is the case that the
//input file has only odd index number to store
{
indexbuf[1]=END;//put a special index number
//(the max number of the dictionary) END to the
code file
zipOutput(out,indexbuf);
count2+=3;
}
dic.add(str);
in.close ();
out.close ();
System.out.println("zip rate:"+(float)count2*100/count1+"% ");
}catch(IOException e )
{
System.err.println(e);
return;
}
catch(OutDictionaryException e)
{
System.err.println(e);
return;
}
}
/** input the code stream from a file,and output the char stream to anpther
file
* @param BufferedInputStream in: the input code file
BufferedOutputStream out:the output charstream stream file
* @return No return value
* @exception No return Exception
*
*
*/ public void decode(BufferedInputStream in,BufferedOutputStream out)
{
System.out.println("decoding...\n"+".......\n");
short precode=0,curcode=0;
String prefix=null;
short i=0;
short bufcode[]=new short[2];//2 code read from the code file
boolean more=true;//indicate the end of the file or some error while
input the file
// DataOutputStream out2=new DataOutputStream(out);
try{
more=zipInput(in,bufcode);//first input 2 code
if(more)
{
curcode=bufcode[0];
// out2.writeChars(dic.getString(curcode));
stringOut(out,dic.getString(curcode) );
}
else
System.out.println("error in the beginning...");
while(more)
{
precode=curcode;
if(i==0)
{
curcode=bufcode[1];
i=1;
}
else
{
more=zipInput(in,bufcode);
curcode=bufcode[0];
if(bufcode[1]==END)
{
stringOut(out,dic.getString (bufcode[0] ));
break;
}
i=0;
}