java哈夫曼压缩和解压_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java哈夫曼压缩和解压

java哈夫曼压缩和解压

 2014/11/11 16:03:24  我就是CT  程序员俱乐部  我要评论(0)
  • 摘要:文件压缩和解压系统这是我把之前学的哈夫曼压缩给系统化,界面化了,变成了一个可以执行的文件,里面的压缩只能给小文件进行压缩(注:这个压缩不会把原文件压坏,所以大家放心的压),如果对大文件压缩的化,会报错,并且压缩后的东西不是个东西,不能还原。而且,压缩后是乱码,可以用来加密哦。本压缩系统的有点在于:用2个线程来分别进行压缩和解压过程,不会当你按下压缩按钮时,按钮不会弹起来,直到压缩完成后才弹起来;压缩结束后会有提示,方便用户使用。这里把最终的可以执行的程序上传,由于文件超过10m,所以分开上传
  • 标签:

文件压缩和解压系统

这是我把之前学的哈夫曼压缩给系统化,界面化了,变成了一个可以执行的文件,里面的压缩只能给小文件进行压缩(注:这个压缩不会把原文件压坏,所以大家放心的压),如果对大文件压缩的化,会报错,并且压缩后的东西不是个东西,不能还原哭哭。而且,压缩后是乱码,可以用来加密哦酷酷

本压缩系统的有点在于:用2个线程来分别进行压缩和解压过程,不会当你按下压缩按钮时,按钮不会弹起来,直到压缩完成后才弹起来;压缩结束后会有提示,方便用户使用。这里把最终的可以执行的程序上传,由于文件超过10m,所以分开上传,大家下载后请把它们解压到同一个路径下。不然不能执行!

?

接着是提供代码的时候了

这是界面代码:

?

class="java" name="code">package 大二lesson01;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

    /** 
     * 哈夫曼压缩主类,实现压缩(英文可压缩) 
     * @author 客 
     * 
     */  
	@SuppressWarnings("serial")
	public class HuffmanTest extends JFrame{ 
		//用来保存中途获取的文件名信息
		private static String name;
		private static File file;
		 //被解压缩文件路径  
	    static String path1 = "";  
	    //解压缩后的文件路径  
	    static String newPath1 = "";  
		private static JTextField jt1,jt2,jt3,jt4;
        //压缩文章的路径  
        static String path = "";  
        //压缩到的路径  
        static String newPath = "";  
        /*
         * 这是压缩的界面
         */
        public static void init_ya(){
        	final JFrame jf_ya=new JFrame();
        	jf_ya.setTitle("文件压缩系统");
        	jf_ya.setLocation(530,175);
        	jf_ya.setResizable(false);
        	jf_ya.setSize(300, 300);
        	jf_ya.setIconImage(new ImageIcon("4.gif").getImage());//添加方框的图标
        	
        	JPanel center = new JPanel();
        	center.setLayout(new GridLayout(2,3));
        	JPanel south = new JPanel();
        	
        	JButton btn_ya = new JButton("开始压缩(Enter)");
        	JButton btn_fanhui = new JButton("返回(Backspace)");
        	JButton btn_xuanze1 = new JButton("选择");
        	JButton btn_xuanze2 = new JButton("选择");
        	
        	jt1 = new JTextField(6);
        	jt2 = new JTextField(6);
        	
        	JLabel jl1 = new JLabel("选择压缩文件:",JLabel.CENTER);
        	JLabel jl2 = new JLabel("压缩到:",JLabel.CENTER);
        	JLabel jl3=new JLabel(new ImageIcon("6.gif"));
        	jl3.setPreferredSize(new Dimension(30,180));
        	
        	center.add(jl1);
        	center.add(jt1);
        	center.add(btn_xuanze1);
        	center.add(jl2);
        	center.add(jt2);
        	center.add(btn_xuanze2);
        	south.add(btn_ya);
        	south.add(btn_fanhui);
        	
        	jf_ya.add(jl3,BorderLayout.NORTH);
        	jf_ya.add(center,BorderLayout.CENTER);
        	jf_ya.add(south,BorderLayout.SOUTH);
        	
        	jf_ya.setVisible(true);
        	//返回按钮
        	btn_fanhui.addActionListener(new ActionListener() {
        		
        		public void actionPerformed(ActionEvent e) {
        			jf_ya.setVisible(false);
        			init_First();
        		}
        	});
        	//选择文件按钮
        	btn_xuanze1.addActionListener(new ActionListener() {
        		
        		public void actionPerformed(ActionEvent e) {
        			JFileChooser jc = new JFileChooser();
        			jc.showOpenDialog(jf_ya);
        			file = jc.getSelectedFile();
        			name = file.getName();
        			jt1.setText(file.getAbsolutePath());
        		}
        	});
        	//选择路径按钮
        	btn_xuanze2.addActionListener(new ActionListener() {
        		
        		public void actionPerformed(ActionEvent e) {
        			JFileChooser jc = new JFileChooser();
        			jc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        			jc.showOpenDialog(jf_ya);
        			file = jc.getSelectedFile();
        			jt2.setText(file.getAbsolutePath());
        		}
        	});
        	//压缩按钮
        	btn_ya.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
						path=jt1.getText();
	    	            String str = "\\压缩"+name;
	    	            newPath=jt2.getText()+str;	
						
					 	HuffmanTest_Thread h_t = new HuffmanTest_Thread(path, newPath);
					 	h_t.start();
				}
			});
        }
        /*
         * 这是主的界面
         */
        public static void init_First(){
        	final JFrame jf_first = new JFrame("文件压缩系统");
        	
        	jf_first.setSize(300,300);
        	jf_first.setLocation(530,175);
        	jf_first.setResizable(false);
        	jf_first.setDefaultCloseOperation(3);
        	jf_first.setIconImage(new ImageIcon("4.gif").getImage());//添加方框的图标
        	
        	JPanel pa = new JPanel();
        	
        	JButton btn_ya = new JButton("压缩");
        	JButton btn_jie = new JButton("解压");
        	
        	JLabel jl3=new JLabel(new ImageIcon("1.gif"));
        	jl3.setPreferredSize(new Dimension(30,240));
        	
        	pa.add(btn_ya);
        	pa.add(btn_jie);
        	
        	jf_first.add(jl3,BorderLayout.NORTH);
        	jf_first.add(pa,BorderLayout.CENTER);
        	
        	jf_first.setVisible(true);
        	//解压按钮
        	btn_jie.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					init_jie();
					jf_first.setVisible(false);
				}
			});
        	//压缩按钮
        	btn_ya.addActionListener(new ActionListener() {
        		public void actionPerformed(ActionEvent e) {
        			init_ya();
        			jf_first.setVisible(false);
        		}
        	});
        }
        /*
         * 这是解压缩的界面
         */
        public static void init_jie(){
        	final JFrame jf_jie=new JFrame("文件解压系统");
        	
        	jf_jie.setLocation(530,175);
        	jf_jie.setResizable(false);
        	jf_jie.setSize(300, 300);
        	jf_jie.setIconImage(new ImageIcon("4.gif").getImage());//添加方框的图标
        	
        	JPanel center = new JPanel();
        	//中间面板设置表格布局
        	center.setLayout(new GridLayout(2,2));
        	JPanel south = new JPanel();
        	
        	JButton btn_jie = new JButton("开始解压(Enter)");
        	JButton btn_fanhui = new JButton("返回(Backspace)");
        	JButton btn_xuanze1 = new JButton("选择");
        	JButton btn_xuanze2 = new JButton("选择");
        	
        	 jt3 = new JTextField(6);
        	 jt4 = new JTextField(6);
        	 
        	JLabel jl1 = new JLabel("选择解压文件:",JLabel.CENTER);
        	JLabel jl2 = new JLabel("解压到:",JLabel.CENTER);
        	JLabel jl3=new JLabel(new ImageIcon("8.gif"));
        	jl3.setPreferredSize(new Dimension(30,180));
        	
        	center.add(jl1);
        	center.add(jt3);
        	center.add(btn_xuanze1);
        	center.add(jl2);
        	center.add(jt4);
        	center.add(btn_xuanze2);
        	south.add(btn_jie);
        	south.add(btn_fanhui);
        	
        	jf_jie.add(jl3,BorderLayout.NORTH);
        	jf_jie.add(center,BorderLayout.CENTER);
        	jf_jie.add(south,BorderLayout.SOUTH);
        	
        	jf_jie.setVisible(true);
        	//选择文件的按钮
        	btn_xuanze1.addActionListener(new ActionListener() {
        		public void actionPerformed(ActionEvent e) {
        			JFileChooser jc = new JFileChooser();
        			jc.showOpenDialog(jf_jie);
        			file = jc.getSelectedFile();
        			name = file.getName();
        			jt3.setText(file.getAbsolutePath());
        		}
        	});
        	//选择路径的按钮
        	btn_xuanze2.addActionListener(new ActionListener() {
        		public void actionPerformed(ActionEvent e) {
        			JFileChooser jc = new JFileChooser();
        			jc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        			jc.showOpenDialog(jf_jie);
        			file = jc.getSelectedFile();
        			jt4.setText(file.getAbsolutePath());
        		}
        	});
        	//返回按钮
        	btn_fanhui.addActionListener(new ActionListener() {
        		public void actionPerformed(ActionEvent e) {
        			jf_jie.setVisible(false);
        			init_First();
        		}
        	});
        	//解压按钮
        	btn_jie.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				path1 = jt3.getText();
		        	String str = "\\解"+name;
		            newPath1=jt4.getText()+str;
    				HuffmanTestThread ht = new HuffmanTestThread(path1, newPath1);
    				ht.start();
    			}
    		});
        }
        /** 
         * 程序入口,主方法 
         * @param args 
         * @throws IOException  
         */  
        public static void main(String[] args) throws IOException{  
        	init_First();
        }  
    }  

?这是压缩的线程和算法代码:

?

package 大二lesson01;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.PriorityQueue;

import javax.swing.JOptionPane;


public class HuffmanTest_Thread extends Thread{
	static HeadInfo[] head;  
    //记录总共有多少个字符  
    static int codeNum;
    //压缩文章的路径  
    private String path = "";  
    //压缩到的路径  
    private String newPath = "";  
    //记录文章中字符和频率的数组,下标表示字符的ASCII码,数组内容表示该字符的出现次数  
    static int[] byteCount = new int[256];  
    //哈夫曼树的根节点  
    static hfmNode root;  
    //传入“给叶子节点设置编码的方法”中  
    static String s = "";  
    //存储ascii为下标值的字符的编码对象,它是码表,是初始的编码,不补0的  
    static Code SaveCode[] = new Code[256];  
    //存储ascii为下标值的字符的编码需要的补0数  
    static int zeroCount[] = new int[256];  
    static FileInputStream fis;  
    static FileOutputStream fos;  
    //记录文件内容所有的原始编码的字符串,用以统计文件末尾的补零个数  
    static int allString = 0;  
         //文件末尾补零的个数  
    static int fileAddZero;
	public HuffmanTest_Thread(String path,String newPath){
		this.path = path;
		this.newPath = newPath;
	}
	public void run(){
		 try {
			 	//遍历文件统计每个字符的出现次数,并且记录字符的ASCII码 
				countWeight(path);
	            //根据字符出现次数,建立哈夫曼树,方法末尾得到树的根节点  
	            createTree();  
	            //给叶子节点设置编码  
	            setCode(root, s);  
	            //写入文件头信息  
				writeHead(newPath);
	            //写入文件  
	            writeFile(path); 
	            JOptionPane.showMessageDialog(null, "Done");
	            } catch (IOException e1) {
					e1.printStackTrace();
				}  
	}
	/** 
     * 读取文件统计字符和字符的出现频率 
     * @param path 要压缩的文件路径 
     * @throws IOException  
     */  
    public static void countWeight(String path) throws IOException{  
        fis = new FileInputStream(path);  
        while(fis.available()>0){  
            int i = fis.read();  
            byteCount[i]++;//i是字符的ASCII码,数组内容是该字符的出现次数  
        }  
    }  
    /** 
     * 根据字符频率,将字符创建成结点加入到优先队列中,建立哈夫曼树 
     */  
    public static void createTree(){  
        //使用优先队列  
        PriorityQueue<hfmNode> nodeQueue = new PriorityQueue<hfmNode>();          
        for(int i=0;i<byteCount.length;i++){  
//          System.out.println(byteCount[i]);  
            if(byteCount[i]!=0){//文件中出现次数不为0的字符,建立哈夫曼结点,存入队列  
                hfmNode node = new hfmNode(i,byteCount[i]);               
                nodeQueue.add(node);  
            }  
        }         
        //根据优先队列的排序,构建哈夫曼树  
        while(nodeQueue.size()>1){//当队列中的元素个数大于1  
            //取得最小的两个,并删除掉  
            hfmNode min1 = nodeQueue.poll();  
            hfmNode min2 = nodeQueue.poll();  
            //建立新的结点  
            hfmNode result = new hfmNode(0,min1.getTimes()+min2.getTimes());  
            //设置新结点的左右子结点  
            result.setlChild(min1);  
            result.setrChild(min2);  
            //新结点加入到优先队列中  
            nodeQueue.add(result);  
        }  
        //循环结束后队列中只有一个元素,该元素就是根节点,获取到但不删除  
        root = nodeQueue.peek();  
//        System.out.println("根!"+root.toString());  
    }  
    /** 
     * 给叶子节点设置编码 
     * @param root 
     * @param s 
     */  
    public static void setCode(hfmNode root,String s){  
        //如果左右子结点都为空,即为叶子节点  
        if(root.getlChild()==null&&root.getrChild()==null){  
            //实例化一个code对象,设置编码和长度  
            Code huffman_code = new Code();  
            huffman_code.setCode(s);  
            //把编码code对象放到SaveCode数组中下标为字符ascii值  
            SaveCode[root.getAscii()] = huffman_code;  
            //输出编码信息  
//          System.out.println(SaveCode[root.getAscii()].toString());  
        }  
        //如果左子结点不为空,递归  
        if(root.getlChild()!=null){  
            setCode(root.getlChild(),s+'0');  
        }  
        //如果右子结点不为空,递归  
        if(root.getrChild()!=null){  
            setCode(root.getrChild(),s+'1');  
        }         
    }  
  
    /** 
     * 写入文件头信息,写入的编码是补零后的编码 
     * 然后把码表写入文件头信息 
     * @throws IOException  
     */  
    public static void writeHead(String newPath) throws IOException{  
        fos = new FileOutputStream(newPath);  
        //统计文件总共用到的字符总数,即编码个数  
        int codeNum = 0;  
        for(int i=0;i<256;i++){  
            if(SaveCode[i]!=null){  
                codeNum++;  
                allString += byteCount[i]*SaveCode[i].getCode().length();  
            }  
        }  
        //写入总文件中总共有多少个用到的字符  
        fos.write(codeNum);  
//        System.out.println(codeNum);  
        //循环输出码表,包括(按顺序):字符、补了几个0、编码含有的byte个数、编码(整型)。  
        for(int i=0;i<256;i++){  
            //如果该字符在文件中出现过,即编码不为空  
            if(SaveCode[i]!=null){  
                //写入:字符的ASCII码值  
                fos.write(i);     
//                System.out.print(i+"\t"+(char)i);  
                //第i个字符的补零数  
                if(SaveCode[i].getCode().length()%8!=0){//如果编码字符串程度不是8的整倍数  
                    zeroCount[i] = 8-SaveCode[i].getCode().length()%8;//设置补零的个数   
                }else{//如果是8的整倍数  
                    zeroCount[i] = 0;  
                }  
                //写入:每个编码末尾补了几个0  
                fos.write(zeroCount[i]);  
                //补零后的编码,写入头信息  
                String addZero = SaveCode[i].getCode();  
//                System.out.println(SaveCode[i].getCode()+"需要补零的个数"+zeroCount[i]);  
                for(int j=0;j<zeroCount[i];j++){//循环次数为:需要补零的个数  
                    //每次在编码后补一个0  
//                  SaveCode[i].setCode(SaveCode[i].getCode()+'0');  
                    addZero = addZero+'0';  
                }  
                //在补0完成后,写入:编码有几个byte  
                fos.write(addZero.length()/8);  
//              System.out.print(addZero.length()/8+"\t");  
                //对于补齐0的编码,每次取出一个字节  
                for(int j=0;j<addZero.length()/8;j++){  
                    String subString = "";  
                    //取出一个字节中的8位赋值给codeString  
                    for(int k=j*8;k<(j+1)*8;k++){  
                        subString = subString+addZero.charAt(k);                      
                    }                     
                    //读取每个字节,将01串转化成整型数  
                    int cs = changeString(subString);                 
                    fos.write(cs);  
//                  System.out.print(cs+"  ");  
                }//每个字符读取完毕  
                  
//              System.out.println("\t"+zeroCount[i]);  
            }  
        }  
        if(allString%8==0){  
            fos.write(0);  
        }else{  
            fileAddZero = 8-allString%8;  
            fos.write(fileAddZero);  
//            System.out.println("文章末尾补零"+fileAddZero);  
        }  
    }  
    /** 
     * 读文件并写入内容 
     * @throws IOException  
     */  
    public static void writeFile(String path) throws IOException{  
//        System.out.println("xxxxxxx");  
        //等待中的编码字符串  
        String str = "";  
        fis = new FileInputStream(path);  
        //如果文件可读内容大于0  
        while(fis.available()>0){  
            //读取一个字节字符  
            int i = fis.read();  
            //得到该字符的码表中的编码----没有补零的,加入到等待中的字符串后  
            str = str+SaveCode[i].getCode();  
              
//            System.out.println("!!~~!!"+str);  
              
            //如果该编码长度大于等于8  
            while(str.length()>=8){  
                //截取8位编码的字符串  
                String subString = "";  
                for(int j=0;j<8;j++){  
                    subString = subString+str.charAt(j);  
                }  
                //读取每个字节,将01串转化成整型数  
                int cs = changeString(subString);  
                fos.write(cs);  
                //删除str的前八位  
                String tranString = str;  
                str = "";  
                for(int j=8;j<tranString.length();j++){  
                    str = str+tranString.charAt(j);  
                }  
            }  
//          System.out.println("sssssssssssssssssssss"+str);  
        }  
        //文件末尾最后的字符串  
//        System.out.println("mm"+str);  
        for(int t=0;t<fileAddZero;t++){  
            str = str+'0';  
        }  
//        System.out.println(str);  
        //写入文件  
        int cs = changeString(str);   
        fos.write(cs);  
    }     
    /** 
     * 将8个字符的字符串转换成01串对应的整数 
     * @param s 
     * @return 
     */
    private static int changeString(String s) {  
        return ((int)s.charAt(0)-48)*128+((int)s.charAt(1)-48)*64  
                +((int)s.charAt(2)-48)*32+((int)s.charAt(3)-48)*16  
                +((int)s.charAt(4)-48)*8+((int)s.charAt(5)-48)*4  
                +((int)s.charAt(6)-48)*2+((int)s.charAt(7)-48);  
    }  
}

??这是解压缩的线程和算法代码:

package 大二lesson01;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JOptionPane;
public class HuffmanTestThread extends Thread{
	 //被解压缩文件路径  
    private  String path1 = "";  
    //解压缩后的文件路径  
    private  String newPath1 = ""; 
    static HeadInfo[] head;  
    //记录总共有多少个字符  
    static int codeNum;
    static int[] byteCount = new int[256];  
    static FileInputStream fis;  
    static FileOutputStream fos;  
    //文件末尾补零的个数  
    static int fileAddZero;  
      
	public HuffmanTestThread(String path1,String newPath1){
		this.path1=path1;
		this.newPath1=newPath1;
	}
	public void run(){
		try {
		readHead(path1);
        //读取文件内容并输出  
        readFile(path1,newPath1);
        JOptionPane.showMessageDialog(null, "Done");
        } catch (IOException e1) {
			e1.printStackTrace();
		}  
	}
    /** 
     * 读取文件头信息,按写入的顺序依次读出: 
     * 1、字符种类总数, 
     * 2、字符ASCII码,编码末尾补零数,字符占字节数,编码 
     * 3、文件末尾补零数 
     *  
     * @throws IOException  
     */  
    public static void readHead(String path) throws IOException{  
        fis = new FileInputStream(path);  
        //读取字符种类总数  
        codeNum = fis.read();  
//        System.out.println(codeNum);  
        //实例化记录文件头信息的数组,数组长度为字符种类总数  
        head = new HeadInfo[codeNum];  
//        System.out.println("ascii\t字节数\t补零数\t编码");  
        //以字符种类总数作为循环限制条件,读取每个字符的编码细则  
        for(int i=0;i<codeNum;i++){  
            //创建文件头信息对象  
            HeadInfo info = new HeadInfo();  
            //读取字符ASCII码,给对象设置ASCII码  
            info.setAscii(fis.read());  
//            System.out.print(info.getAscii()+"\t"+(char)info.getAscii()+"  ");  
            //读取编码末尾补零数,并给对象设置  
            info.setZeroNum(fis.read());  
            //读取编码所占字节数,给对象设置  
            info.setByteNum(fis.read());  
//            System.out.print(info.getByteNum()+"\t");  
            //读取当前编码的每个字节  
            for(int j=0;j<info.getByteNum();j++){  
                int code_int = fis.read();  
                //读取到的整数转换成String---0,1串,该01串不会以0开头  
                String code_string = Integer.toBinaryString(code_int);  
//              System.out.println("s++"+code_string);  
                int length = code_string.length();  
                //01串不足8位的在前面补零  
                if(length%8!=0){  
                    for(int k=0;k<8-length;k++){  
                        code_string = '0'+code_string;                        
                    }  
                }  
                //给info对象设置编码,含补零,每个字节的前面补零的01串相加  
                info.setCode(info.getCode()+code_string);                 
            }  
            //得到完整的补零后的01串,即文件头信息存储的编码  
//            System.out.print(info.getZeroNum()+"\t");  
            //根据编码末尾补零个数,恢复编码不补零的编码,即码表中存储的编码,  
            for(int t=0;t<info.getZeroNum();t++){  
                info.setCode(info.getCode().substring(0, info.getCode().length()-1));  
            }  
//            System.out.println("去0后  "+info.getCode());   
            //将info对象添加到数组中  
            head[i] = info;  
        }  
        //读取头信息的最后一个内容:文章末尾的补零的个数  
        fileAddZero = fis.read();  
//        System.out.println("文件末尾补零"+fileAddZero);         
    }     
    /** 
     * 读取文件内容,写入新文件,完成解压缩 
     * @throws IOException  
     */  
    public static void readFile(String path,String newPath) throws IOException{  
        fos = new FileOutputStream(newPath);  
        //等待转换的字符串  
        String str = "";  
        //当文件可读信息大于零时  
        while(fis.available()>0){  
            //读取一个字节,赋值给整数txt  
            int txt = fis.read();  
            //将该整数转换成01串,该字符串不会以0开头  
            String temp = Integer.toBinaryString(txt);  
//            System.out.println(temp+"   nnnn");  
              
            //给转换成的01串,前面补零成完整的8位的字符串  
            int frontAddZero = temp.length()%8;  
            if(frontAddZero!=0){  
                for(int i=0;i<8-frontAddZero;i++){  
                    temp = '0'+temp;                  
                }  
            }  
//            System.out.println(temp+">>>>>>>>>>>>");  
            //加到等待转换的字符串后,等待转换  
            str = str+temp;  
//            System.out.println(str+" !!!!等待转换!!!!");  
          
            for(int j=0;j<codeNum;j++){  
                //判断当前等待转换的字符串,是否以码表中的某个编码开头  
                if(str.startsWith((head[j].getCode()))){  
                    //如果是,写入这个编码对应的字符  
//                    System.out.println(str+"  ========  "+head[j].getCode());                         
//                  System.out.println("qqqq"+i);  
//                    System.out.println((char)head[j].getAscii());  
                    fos.write(head[j].getAscii());  
//                    
                    //将等待转换的字符串去掉已经写入的编码部分  
                    String tran = str;  
                    str = "";  
                    for(int k=head[j].getCode().length();k<tran.length();k++){  
                        str = str+tran.charAt(k);  
                    }  
                    //设置循环从头开始判断现在的str是否以某编码开头  
                    j = -1;  
                    //如果此时已经没有可读的文件信息了  
                    if(fis.available()==0){  
                        //将文件末尾添加的0的个数,在str中删去  
                        String tra = str;  
                        str = "";  
                        for(int t=0;t<tra.length()-fileAddZero;t++){  
                            str = str+tra.charAt(t);  
                        }  
                        //如果删去之后字符串空了,那么跳出循环,文件读取完毕  
                        if(str==""){  
                            break;  
                        }  
                        //如果str不为空,那么继续j=-1的地方循环判断是否以某编码开头  
                    }  
                }             
            }//for循环      
        }//while循环  
        //确认文件读取完毕  
//        System.out.println(str.length()+" 最后str的长度");  
    }  
}

?以下三个是辅助类:

package 大二lesson01;

public class Code {  
    //哈夫曼编码  
    private String code = "";     
    /** 
     * 输出Code类对象的方法 
     */  
    public String toString(){  
        return "编码:"+code+"  长度:"+code.length();  
    }  
    /** 
     * 得到编码内容 
     * @return 
     */  
    public String getCode() {  
        return code;  
    }  
    /** 
     * 设置编码内容 
     * @param code 
     */  
    public void setCode(String code) {  
        this.code = code;  
    }  
}  

?**********************

package 大二lesson01;

public class hfmNode implements Comparable<hfmNode>{  
    //字符的ASCII码值  
    private int ascii;  
    //字符的出现次数  
    private int times;  
    //当前结点的左子结点  
    private hfmNode lChild;  
    //当前结点的右子结点  
    private hfmNode rChild;       
    /** 
     * 构造方法 
     * @param i ASCII的值 
     * @param times 文件中的出现次数 
     */  
    public hfmNode(int ascii,int times){  
        this.ascii = ascii;  
        this.setTimes(times);  
    }     
    /** 
     * 得到结点字符ASCII值得方法 
     * @return ASCII码值 
     */  
    public int getAscii() {  
        return ascii;  
    }     
    /** 
     * 设置结点字符的ASCII值 
     * @param ascii 
     */  
    public void setAscii(int ascii) {  
        this.ascii = ascii;  
    }     
    /** 
     * 得到当前结点字符出现次数的方法 
     * @return 
     */  
    public int getTimes() {  
        return times;  
    }  
    /** 
     * 设置当前结点字符出现次数的方法 
     * @param times 
     */  
    public void setTimes(int times) {  
        this.times = times;  
    }  
    /** 
     * 得到当前结点左孩子的方法 
     * @return 左子结点 
     */  
    public hfmNode getlChild() {  
        return lChild;  
    }  
    /** 
     * 设置当前结点左孩子的方法 
     * @param lChild 
     */  
    public void setlChild(hfmNode lChild) {  
        this.lChild = lChild;  
    }  
    /** 
     * 得到当前结点右孩子的方法 
     * @return 右子结点 
     */  
    public hfmNode getrChild() {  
        return rChild;  
    }  
    /** 
     * 设置当前结点右孩子的方法 
     * @param rChild 
     */  
    public void setrChild(hfmNode rChild) {  
        this.rChild = rChild;  
    }  
    /** 
     * 输出hfmNode类对象--哈夫曼结点的方法 
     */  
    public String toString(){  
        return "ascii="+(char)ascii+"             times="+times;  
    }         
    /** 
     * 定义在队列中进行排序比较的属性 
     */  
    public int compareTo(hfmNode o) {  
        return times-o.getTimes();  
    }     
}  

?***********************

package 大二lesson01;

public class HeadInfo {  
    
    //字符ASCII码  
    private int ascii;  
    //字符编码占用字节数  
    private int byteNum;  
    //编码末尾补零数  
    private int zeroNum;  
    //编码  
    private String code = "";  
      
    /** 
     * 得到ASCII码 
     * @return 
     */  
    public int getAscii() {  
        return ascii;  
    }  
      
    /** 
     * 设置ASCII码  
     * @param ascii 
     */  
    public void setAscii(int ascii) {  
        this.ascii = ascii;  
    }  
      
    /** 
     * 得到编码占字节数 
     * @return 
     */  
    public int getByteNum() {  
        return byteNum;  
    }  
      
    /** 
     * 设置编码占字节数 
     * @param byteNum 
     */  
    public void setByteNum(int byteNum) {  
        this.byteNum = byteNum;  
    }  
      
    /** 
     * 得到编码 
     * @return 
     */  
    public String getCode() {  
        return code;  
    }  
      
    /** 
     * 设置编码 
     * @param code 
     */  
    public void setCode(String code) {  
        this.code = code;  
    }  
      
    /** 
     * 得到编码末尾补零个数 
     * @return 
     */  
    public int getZeroNum() {  
        return zeroNum;  
    }  
      
    /** 
     * 设置编码末尾补零个数 
     * @param zeroNum 
     */  
    public void setZeroNum(int zeroNum) {  
        this.zeroNum = zeroNum;  
    }     
}  

?就这么多了,接下来附上我的基本的界面图片:

?

?

?接下来,我将改进算法并且给部分按钮加上键盘监听器,如果大家有什么好的建议或意见,欢迎留言,我会积极采纳的!

  • 文件压缩pic.rar (5.1 MB)
  • 下载次数: 0
  • 文件压缩.rar (7.1 MB)
  • 下载次数: 0
  • 大小: 126.8 KB
  • 大小: 32.6 KB
  • 大小: 55.4 KB
  • 查看图片附件
上一篇: Java中Map相关的快速查找算法与唯一性 . 下一篇: 没有下一篇了!
  • 相关文章
发表评论
用户名: 匿名