哈弗曼编码与反编码的实现 java源代码

哈弗曼编码与反编码的实现  java源代码下载地址:http://download.csdn.net/source/2357457

哈弗曼编码与反编码的实现 java源代码哈弗曼编码与反编码的实现 java源代码

public class Huffman {
	public static void main(String[] args) {
	new	HaffmanFrame();
	
   }
}
 

//主界面类
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//主界面
public class HaffmanFrame extends JFrame implements ActionListener {
	
	private static final long serialVersionUID = 1808617924849665897L;
	private JButton  choice, ok, reset,recoding,re;//choice 文件选择,ok 确定 ,reset 重置,recoding 反编译
	private JLabel choiceJL,codingJL,recodingJL;//选择  编码 反编码 标签
	private JTextArea inputJTA,recodingJTA;
	private JScrollPane js1,js2,js3;
    private HaffmanJTable table ;
    private TotalChars tc = null;
    private HffmanCoding hfc = null;
	HaffmanFrame(){
		super("哈弗曼编码与反编码");
		newFrame();//界面的初始化
        formeValidate();
	}
	@Override 
	public void actionPerformed(ActionEvent e) {
		// TODO 事件的处理
        if(e.getSource() ==  choice) {
        	open();
        }
        else if(e.getSource() == ok) {
        	ok();
       }
        else if(e.getSource() == reset) {
        	reset();
        }
        else if(e.getSource() == recoding) {
        	if(tc != null )
        		{
        		JOptionPane.showMessageDialog(this, hfc.reCoding(recodingJTA.getText()), "反哈弗曼编码文本",
    					JOptionPane.DEFAULT_OPTION);
        		}
        }
        else if(e.getSource() == re) {
        	recodingJTA.setText(null);
        }
	}
	//重置
	private void reset() {
		inputJTA.setText("");
		recodingJTA.setText("");
		table.beginTable();
		table.repaint();
	}
//   确定
	private void ok() {
		table.beginTable();
		table.repaint();
	     tc = new TotalChars();
		int chars[][] = tc.getCharAddWeight(inputJTA.getText());
	     hfc = new HffmanCoding(chars);
		hfc.coding();//哈弗曼树
		String s[] = hfc.CreateHCode();//哈弗曼编码
		for (int i = 0; i < chars.length; i++) {
			
				if (chars[i][0]<= 32)
					table.setT(i, 0, "A" + String.valueOf(chars[i][0]));//以ascll码的形式在表格输出
				else
					table.setT(i, 0, String.valueOf((char) chars[i][0]));//以字符的形式在表格输出
				table.setT(i, 1, String.valueOf(chars[i][1]));
				table.setT(i, 2, s[i]);
		}
		recodingJTA.setText(hfc.show(inputJTA.getText()));
		table.repaint();
	}
//	打开
	private void open() {
		inputJTA.setText("");
		FileOpen fo = new FileOpen(this);
		fo.open();
		inputJTA.setText(fo.getText());
		fo = null;
	}
	
	//界面的初始化
	private void newFrame() {
		table = new HaffmanJTable();
		choice   = new JButton("选择文件");
		ok       = new JButton("确     定");
		reset    = new JButton("重     置");
		recoding = new JButton("反编码");
		re       = new JButton("重置反编码");
		
		choiceJL   = new JLabel("请选择文件或输入文本:");
		codingJL   = new JLabel("字符的哈弗曼编码:");
		recodingJL = new JLabel("文本的哈弗曼编码表示:");
        inputJTA     = new JTextArea(5,5);
        recodingJTA  = new JTextArea(5,5);
        recodingJTA.setLineWrap(true);
        js1 = new JScrollPane(inputJTA); 
        js2 = new JScrollPane(table.myTable()); 
        js3 = new JScrollPane(recodingJTA); 
        
        //设置位置
        choiceJL.setBounds(10, 10, 150, 30);
        js1.setBounds(160, 10, 320, 150);
        ok.setBounds(200, 170, 80, 30);
        reset.setBounds(350, 170, 80, 30);
        choice.setBounds(30,50,100,30);
        codingJL.setBounds(10, 210, 150, 30);
        js2.setBounds(160, 210, 320, 150);
        recodingJL.setBounds(10, 370, 150, 30);
        js3.setBounds(160, 370, 320, 150);
        recoding.setBounds(30, 410, 100, 30);
        re.setBounds(30, 450, 100, 30);
        
        this.setLayout(null);
        this.add(choiceJL);
        this.add(js1);
        this.add(ok);
        ok.addActionListener(this);
        this.add(reset);
        reset.addActionListener(this);
        this.add(choice);
        choice.addActionListener(this);
        this.add(re);
        re.addActionListener(this);
        this.add(codingJL);
        this.add(js2);
        this.add(recodingJL);   
        this.add(js3);
        this.add(recoding);
        recoding.addActionListener(this);
        
        Font f = new Font("宋体",Font.BOLD,15);//设置字体
        inputJTA.setFont(f);
        recodingJTA.setFont(f);
	}
	private void formeValidate() {
		Toolkit tk = getToolkit();//获得屏幕的宽和高
		Dimension dim = tk.getScreenSize(); 
	    this.setResizable(false);
		this.setBounds(dim.width/2-250, dim.height/2-280,500,570); 
        setVisible(true);
        validate();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
 

//表格类
import java.awt.Component;
import java.awt.Font;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class HaffmanJTable {
	private JTable table;
	private Object t[][] = new Object[100][3];//用来存放字符  次数   和哈弗曼编码
	private Object name[] = {"字符","次数","哈弗曼编码"};//用来存放表头
	public Component myTable() {
		// TODO Auto-generated method stub
		table    = new JTable(t,name);
		Font f = new Font("宋体",Font.BOLD,15);//设置字体
		table.setFont(f);
		setColumnSize(0,40);//设置第1列的大小
		setColumnSize(1,60);//设置第2列的大小
		setColumnSize(2,202);//设置第3列的大小
		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);//AUTO_RESIZE_OFF 
                                                       // 不自动调整列的宽度;使用滚动条。
		                                               //table.setAutoResizeMode()当调整表的大小时,设置表的自动调整模式。
		return table;
	}
	public void setT(int i ,int j, String volue) {//设置表格的值
		this.t[i][j] = volue;
	}
	public void setColumnSize(int i, int width ) {
		TableColumnModel   cm   =   table.getColumnModel();     //表格的列模型
		TableColumn   column  = cm.getColumn(i);//得到第i个列对象   
		column.setPreferredWidth(width);//将此列的首选宽度设置为 preferredWidth。
		//如果 preferredWidth 超出最小或最大宽度,则将其调整为合适的界限值。 
	}
	public void repaint() {//重绘表格
		table.repaint();
	}
	public void beginTable()//重值表格
	{
		for (int i = 0; i < 100; i++) {
			for (int j = 0; j < 3; j++)
				setT(i, j, "");
		}
	}
}
 

//文件的打开
import java.awt.FileDialog;
import java.awt.event.*;
import java.io.*;
import java.io.File;
import java.io.FileReader;
public class FileOpen {
	private FileDialog filedialog_open;
	private String fileopen = null, filename = null;// 用于存放打开文件地址 和文件名
	private File file1; // 文件字节流对象
	private FileReader file_reader;//文件字符流对象
	private BufferedReader in;//文件行读取 写入对象
	private StringBuffer text = new StringBuffer();
	
	HaffmanFrame haffman= null;
	FileOpen(HaffmanFrame hf) {
		haffman = hf;
		filedialog_open = new FileDialog(haffman, "打开文件对话框", FileDialog.LOAD);
		// 打开文件对话框适配器
		filedialog_open.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				filedialog_open.setVisible(false);
			}
		});
	}
	public void open() {
		String s = ""; 
		filedialog_open.setVisible(true);
		fileopen = filedialog_open.getDirectory();// 返回文件对话框中显示的文件所属的目录
		filename = filedialog_open.getFile();// 返回当前文件对话框中显示的文件名的字符串表示
												// 如果不存在就返回NULL
		if (filename != null)// 判断打开的文件是否存在
		{
			try {
				file1 = new File(fileopen,filename );
				file_reader = new FileReader(file1);
	            in = new BufferedReader(file_reader);//每次读取一行
	            while ((s = in.readLine()) != null)
			    text.append(s + '/n');
			    in.close();
	            file_reader.close();
			} catch (IOException e2) {
				System.out.println("不能打开文件!");
			}
		}
	}
	//返回得到的文本字符串
	public String getText() {
		return new String(text);
	}
}
 

//统计字符类
public class TotalChars {
	private int charCount[] = new int[255];
	private char c[];//统计字符的个数
	private int  charAddWeight[][];//存放字符的ascll码值和字符的频率
	private int  total = 0;//存放需要编码字符的个数
	TotalChars(){
	for(int i = 0; i<255;i++)
		charCount[i] = 0;
	}
    //统计每个字符的出现的个数
	public void charToal(String s) {
		
		c = new char[s.length()];
		c = s.toCharArray();// 将字符串转化为字符数组
		for (int  i = 0; i < c.length; i++) {
			 int j = c[i];
			 charCount[j]++;  
		}
		for(int i = 0; i < 255 ; i++) {
			if (charCount[i] != 0) {
				total++;//统计字符的个数
			}
		}
	}
	
	//	返回字符的ascll码值和字符的频率
	public int[][] getCharAddWeight(String s){
		charToal(s);//统计每个字符的出现的个数
		charAddWeight = new  int[total][2];
		for(int i = 0,j=0; i < 255 ; i++) {
			
				if (charCount[i] != 0) {
					charAddWeight[j][0] = i;
					charAddWeight[j++][1] = charCount[i];
				}
		}	
		return charAddWeight;	
	}		
}
 

//哈弗曼编码的实现类
public class HffmanCoding {
	private int charsAndWeight[][];// [][0]是 字符,[][1]存放的是字符的权值(次数)
	private int hfmcoding[][];// 存放哈弗曼树
	private int i = 0;// 循环变量
	private String hcs[];
	public HffmanCoding(int[][] chars) {
		// TODO 构造方法
		charsAndWeight = new int[chars.length][2];
		charsAndWeight = chars;
		hfmcoding = new int[2 * chars.length - 1][4];// 为哈弗曼树分配空间
	}
	// 哈弗曼树的实现
	public void coding() {
		int n = charsAndWeight.length;
		if (n == 0)
			return;
		int m = 2 * n - 1;
		// 初始化哈弗曼树
		for (i = 0; i < n; i++) {
			hfmcoding[i][0] = charsAndWeight[i][1];// 初始化哈弗曼树的权值
			hfmcoding[i][1] = 0;// 初始化哈弗曼树的根节点
			hfmcoding[i][2] = 0;// 初始化哈弗曼树的左孩子
			hfmcoding[i][3] = 0;// 初始化哈弗曼树的右孩子
		}
		for (i = n; i < m; i++) {
			hfmcoding[i][0] = 0;// 初始化哈弗曼树的权值
			hfmcoding[i][1] = 0;// 初始化哈弗曼树的根节点
			hfmcoding[i][2] = 0;// 初始化哈弗曼树的左孩子
			hfmcoding[i][3] = 0;// 初始化哈弗曼树的右孩子
		}
		// 构建哈弗曼树
		for (i = n; i < m; i++) {
			int s1[] = select(i);// 在哈弗曼树中查找双亲为零的 weight最小的节点
			hfmcoding[s1[0]][1] = i;// 为哈弗曼树最小值付双亲
			hfmcoding[s1[1]][1] = i;
			hfmcoding[i][2] = s1[0];// 新节点的左孩子
			hfmcoding[i][3] = s1[1];// 新节点的右孩子
			hfmcoding[i][0] = hfmcoding[s1[0]][0] + hfmcoding[s1[1]][0];// 新节点的权值是左右孩子的权值之和
		}
	}
	// 查找双亲为零的 weight最小的节点
	private int[] select(int w) {
		// TODO Auto-generated method stub
		int s[] = { -1, -1 }, j = 0;// s1 最小权值且双亲为零的节点的序号 , i 是循环变量
		int min1 = 32767, min2 = 32767;
		for (j = 0; j < w; j++) {
			if (hfmcoding[j][1] == 0) {// 只在尚未构造二叉树的结点中查找(双亲为零的节点)
				if (hfmcoding[j][0] < min1) {
					min2 = min1;
					s[1] = s[0];
					min1 = hfmcoding[j][0];
					s[0] = j;
				} else if (hfmcoding[j][0] < min2) {
					min2 = hfmcoding[j][0];
					s[1] = j;
				}
			}
		}
		return s;
	}
	public String[] CreateHCode() {// 根据哈夫曼树求哈夫曼编码
		int n = charsAndWeight.length;
		int i, f, c;
		String hcodeString = "";
		hcs = new String[n];
		for (i = 0; i < n; i++) {// 根据哈夫曼树求哈夫曼编码
			c = i;
			hcodeString = "";
			f = hfmcoding[i][1]; // f 哈弗曼树的根节点
			while (f != 0) {// 循序直到树根结点
				if (hfmcoding[f][2] == c) {// 处理左孩子结点
					hcodeString += "0";
				} else {
					hcodeString += "1";
				}
				c = f;
				f = hfmcoding[f][1];
			}
			hcs[i] = new String(new StringBuffer(hcodeString).reverse());
		}
		return hcs;
	}
	public String show(String s) {// 对字符串显示编码
		String textString = "";
		char c[];
		int k = -1;
		c = new char[s.length()];
		c = s.toCharArray();// 将字符串转化为字符数组
		for (int i = 0; i < c.length; i++) {
			k = c[i];
			for (int j = 0; j < charsAndWeight.length; j++)
				if (k == charsAndWeight[j][0])
					textString += hcs[j];
		}
		return textString;
	}
	// 哈弗曼编码反编译
	public String reCoding(String s) {
		String text = "";// 存放反编译后的字符
		int k = 0, m = hfmcoding.length - 1;// 从根节点开始查询
		char c[];
		c = new char[s.length()];
		c = s.toCharArray();
		k = m;
		for (int i = 0; i < c.length; i++) {
			if (c[i] == '0') {
				k = hfmcoding[k][2];// k的值为根节点左孩子的序号
				if (hfmcoding[k][2] == 0 && hfmcoding[k][3] == 0)// 判断是不是叶子节点,条件(左右孩子都为零)
				{
					text += (char) charsAndWeight[k][0];
					k = m;
				}
			}
			if (c[i] == '1') {
				k = hfmcoding[k][3];// k的值为根节点右孩子的序号
				if (hfmcoding[k][2] == 0 && hfmcoding[k][3] == 0)// 判断是不是叶子节点,条件(左右孩子都为零)
				{
					text += (char) charsAndWeight[k][0];
					k = m;
				}
			}
		}
		return text;
	}
}
 

你可能感兴趣的:(java,String,File,null,Class,import)