Huffman 压缩解压缩java实现

附上完整代码

http://download.csdn.net/download/u010485034/7847447

Huffman编码的原理这里就不说了,网上随处都是。这里来讲讲利用Huffman编码来进行压缩和解压缩的具体实现吧。本工程使用java实现。


编码

1. 流程图


2. 数据结构

CharacterWeight:记录字符值,以及其在待压缩文件中的权重。

Class{
char c; //字符值
int weight;  //在文件中权重
String code;  //其对应huffman编码
}

HuffmanNode:huffman树中的节点信息。

Class{
Int parent;  //父节点
Int lChild; //左儿子
Int rChild;  //右儿子
Int weight; //权重
}

3. 程序关键点

3.1 Huffman树的构建

Huffman树的变量:ArrayList<HuffmanNode> list;

创建流程图:

for(int i=0;i<list.size()-1;i++){
			//w1 : the first min weight w2: the second min weight 
			//i1 : the first min weight index, i2: the second min weight index
			int w1 = MAX_VALUE, w2=MAX_VALUE; 
			int i1 = 0, i2 = 0;
			// find the two node with the minimum weight
			for(int j=0;j<tree.size();j++){
				HuffmanNode node = tree.get(j);
				if(node.getWeight()< w1 && node.getParent()==-1){
					w2 = w1;
					w1 = node.getWeight();
					i2 = i1;
					i1 = j;
				}
				else if(node.getWeight()<w2 && node.getParent()==-1){
					w2 = node.getWeight();
					i2 = j;
				}
			}
			//set the two node to be the children of a new node, and add the new node to the tree
			HuffmanNode pNode = new HuffmanNode(w1+w2);
			pNode.setlChild(i1);
			pNode.setrChild(i2);
			tree.add(pNode);
			tree.get(i1).setParent(tree.indexOf(pNode));
			tree.get(i2).setParent(tree.indexOf(pNode));}

3.2   根据Huffman 树获得Huffman编码

从叶子节点开始网上遍历Huffman树,直到到达根节点,根据当前节点为其父节点的左儿子还是右儿子确定这一位值是0还是1。最后将依次获得的0,1字符串反转获得Huffman编码。

代码:

for(int i=0;i<list.size();i++){
			HuffmanNode node = tree.get(i);
			HuffmanNode pNode = tree.get(node.getParent());
			String code ="";
			while(true){
				if(pNode.getlChild()==tree.indexOf(node)){
					code = "0"+code;
				}
				else if(pNode.getrChild() == tree.indexOf(node)){
					code = "1"+code;
				}
				else {
					System.out.println("Tree Node Error!!!");
					return null;
				}
				node=pNode;
				if(node.getParent()!=-1)
					pNode=tree.get(node.getParent());
				else 
					break;
			}
			list.get(i).setCode(new String(code));
		}
3.3  文件头设计

字符总数

Int 四个字节

字符种类数

Short 两个字节

叶子节点

char字符  short 父节点 3个字节

非叶子节点

Short 左儿子 short 右儿子 short父节点 6字节

 

文件头长度(单位: byte)

l= 9n

其中n 为字符种类数。

3.4文件内容的编码和写入

	while((temp=reader.read())!=-1){ //!= EOF	
				// get the code from the code table
				String code = codeTable.get((char)temp);
				c++;
				if(c>=count/96){
					System.out.print("=");
					c=0;
				}
				try{
					StringBuilder codeString = new StringBuilder(code);
					outputStringBuffer.append(codeString);
					while(outputStringBuffer.length()>8){
						out.write(Short.parseShort(outputStringBuffer.substring(0, 8),2));
						outputStringBuffer.delete(0, 8);
					}
				} catch(Exception e){
					e.printStackTrace();
				}

			}

解码

1. 流程图


2.   数据结构

HuffmanNode:huffman树中的节点信息。

Class{

Int parent;  //父节点

Int lChild; //左儿子

Int rChild;  //右儿子

Int weight; //权重

Char c; //对应的字符值


3.    程序关键点

3.1   重建Huffman树。在文件头中存放的原本就是Huffman树的节点信息,所以重建Huffman树是比较简单的。

代码:

	in = new DataInputStream(new FileInputStream(file));
			count = in.readInt();
			charNum = in.readShort();
			nodeNum = 2*charNum -1;
			//rebuild the huffman tree
			for(int i=0;i<charNum;i++){
				HuffmanNode node = new HuffmanNode((char)in.readByte());
				int parent = in.readShort();
				node.setParent(parent);
				tree.add(node);
			}
			
			for(int i=charNum;i<nodeNum;i++){
				HuffmanNode node = new HuffmanNode(' ');
				int l = in.readShort();
				int r = in.readShort();
				int p = in.readShort();
				node.setlChild(l);
				node.setrChild(r);
				node.setParent(p);
				tree.add(node);
			}

3.2 解码

解码流程图

	while(true){
				while(buff.length()<32){
					temp = in.readInt();
					String codeString = Integer.toBinaryString(temp);
					while(codeString.length()<32){
						codeString='0'+codeString;
					}
					buff.append(codeString);
				}
				node = tree.get(tree.size()-1);
				dep = 0;
				while(!(node.getlChild()==-1&&node.getrChild()==-1)){
					if(dep>=buff.length()){
						System.out.println( "Buff overflow");
					}
					if(buff.charAt(dep)=='0'){
						node = tree.get(node.getlChild());
					}
					else if(buff.charAt(dep)=='1'){
						node = tree.get(node.getrChild());
					}
					else{
						System.out.println("Coding error");
					}
					dep++;
				}
				
				char c = node.getCH();
				num++;
				if(num>=n/99){
					System.out.print("=");
					num=0;
				}
				count++;
				if(count>=n){
					break;
				}
				charBuff+=c;
				if(charBuff.length()>256){
					writer.write(charBuff);
					charBuff="";
				}
				buff.delete(0, dep);
				
			}
			
		} catch(EOFException e){
			//just do nothing
		}
		catch(Exception e){
			e.printStackTrace();
		} finally{
			//there may be data released in the buff and charbuff, so we need to process them
			while(buff.length()>0){
				node = tree.get(tree.size()-1);
				dep = 0;
				while(!(node.getlChild()==-1&&node.getrChild()==-1)){
					if(dep>=buff.length()){
						break;
					}
					if(buff.charAt(dep)=='0'){
						node = tree.get(node.getlChild());
					}
					else if(buff.charAt(dep)=='1'){
						node = tree.get(node.getrChild());
					}
					else{
						System.out.println("Coding error");
						//return;
					}
					dep++;
				}
				char c = node.getCH();
				num++;
				if(num>=n/99){
					System.out.print("=");
					num=0;
				}
				count++;
				if(count>=n){
					break;
				}
				charBuff+=c;
				if(charBuff.length()>256){
					try {
						writer.write(charBuff);
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					charBuff="";
				}
				buff.delete(0, dep);
			}
			
			try {
				writer.write(charBuff);
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
		try{
			writer.close();
		} catch(IOException e){
			throw e;
		}

    完整工程就不放出了,以后再更新吧。
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供Huffman压缩解压缩文件的Java代码。以下是实现的步骤: ## Huffman压缩 1. 读取文件并统计每个字符出现的频率 2. 用字符频率构建Huffman树 3. 遍历Huffman树并生成每个字符的编码 4. 将编码写入输出文件,并将Huffman树写入输出文件 5. 关闭输入输出流 ```java import java.io.*; public class HuffmanCompression { private static final int BYTE_SIZE = 8; public static void compress(String inputFile, String outputFile) throws IOException { FileInputStream inputStream = new FileInputStream(inputFile); int[] frequencies = new int[256]; int totalChars = 0; int nextByte = inputStream.read(); while (nextByte != -1) { frequencies[nextByte]++; totalChars++; nextByte = inputStream.read(); } inputStream.close(); HuffmanNode root = buildHuffmanTree(frequencies); String[] codes = buildCodes(root); FileOutputStream outputStream = new FileOutputStream(outputFile); writeHeader(outputStream, frequencies); writeCompressedData(inputStream, outputStream, codes); outputStream.close(); } private static HuffmanNode buildHuffmanTree(int[] frequencies) { PriorityQueue<HuffmanNode> pq = new PriorityQueue<>(); for (int i = 0; i < frequencies.length; i++) { if (frequencies[i] > 0) { pq.add(new HuffmanNode((byte) i, frequencies[i])); } } while (pq.size() > 1) { HuffmanNode left = pq.poll(); HuffmanNode right = pq.poll(); HuffmanNode parent = new HuffmanNode(left, right); pq.add(parent); } return pq.poll(); } private static String[] buildCodes(HuffmanNode root) { String[] codes = new String[256]; buildCodesHelper(codes, root, ""); return codes; } private static void buildCodesHelper(String[] codes, HuffmanNode node, String code) { if (node.isLeaf()) { codes[node.getByte()] = code; } else { buildCodesHelper(codes, node.getLeft(), code + "0"); buildCodesHelper(codes, node.getRight(), code + "1"); } } private static void writeHeader(FileOutputStream outputStream, int[] frequencies) throws IOException { for (int i = 0; i < frequencies.length; i++) { outputStream.write(frequencies[i]); } } private static void writeCompressedData(FileInputStream inputStream, FileOutputStream outputStream, String[] codes) throws IOException { int currentByte = 0; int numBits = 0; int nextByte = inputStream.read(); while (nextByte != -1) { String code = codes[nextByte]; for (int i = 0; i < code.length(); i++) { currentByte = currentByte << 1; if (code.charAt(i) == '1') { currentByte |= 1; } numBits++; if (numBits == BYTE_SIZE) { outputStream.write(currentByte); currentByte = 0; numBits = 0; } } nextByte = inputStream.read(); } if (numBits > 0) { currentByte = currentByte << (BYTE_SIZE - numBits); outputStream.write(currentByte); } } private static class HuffmanNode implements Comparable<HuffmanNode> { private byte b; private int frequency; private HuffmanNode left; private HuffmanNode right; public HuffmanNode(byte b, int frequency) { this.b = b; this.frequency = frequency; } public HuffmanNode(HuffmanNode left, HuffmanNode right) { this.frequency = left.frequency + right.frequency; this.left = left; this.right = right; } public int getByte() { return b & 0xff; } public int getFrequency() { return frequency; } public boolean isLeaf() { return left == null && right == null; } public HuffmanNode getLeft() { return left; } public HuffmanNode getRight() { return right; } @Override public int compareTo(HuffmanNode o) { return Integer.compare(this.frequency, o.frequency); } } } ``` ## Huffman解压缩 1. 读取文件头并构建Huffman树 2. 读取压缩数据,并根据Huffman树解码 3. 将解码后的数据写入输出文件 4. 关闭输入输出流 ```java import java.io.*; public class HuffmanDecompression { private static final int BYTE_SIZE = 8; public static void decompress(String inputFile, String outputFile) throws IOException { FileInputStream inputStream = new FileInputStream(inputFile); int[] frequencies = new int[256]; for (int i = 0; i < frequencies.length; i++) { frequencies[i] = inputStream.read(); } HuffmanNode root = buildHuffmanTree(frequencies); int totalChars = root.getFrequency(); FileOutputStream outputStream = new FileOutputStream(outputFile); int numBits = 0; int currentByte = 0; HuffmanNode node = root; int nextByte = inputStream.read(); while (nextByte != -1) { for (int i = 0; i < BYTE_SIZE; i++) { int bit = (nextByte >> (BYTE_SIZE - 1 - i)) & 1; if (bit == 0) { node = node.getLeft(); } else { node = node.getRight(); } if (node.isLeaf()) { outputStream.write(node.getByte()); node = root; totalChars--; if (totalChars == 0) { break; } } } nextByte = inputStream.read(); } inputStream.close(); outputStream.close(); } private static HuffmanNode buildHuffmanTree(int[] frequencies) { PriorityQueue<HuffmanNode> pq = new PriorityQueue<>(); for (int i = 0; i < frequencies.length; i++) { if (frequencies[i] > 0) { pq.add(new HuffmanNode((byte) i, frequencies[i])); } } while (pq.size() > 1) { HuffmanNode left = pq.poll(); HuffmanNode right = pq.poll(); HuffmanNode parent = new HuffmanNode(left, right); pq.add(parent); } return pq.poll(); } private static class HuffmanNode implements Comparable<HuffmanNode> { private byte b; private int frequency; private HuffmanNode left; private HuffmanNode right; public HuffmanNode(byte b, int frequency) { this.b = b; this.frequency = frequency; } public HuffmanNode(HuffmanNode left, HuffmanNode right) { this.frequency = left.frequency + right.frequency; this.left = left; this.right = right; } public int getByte() { return b & 0xff; } public int getFrequency() { return frequency; } public boolean isLeaf() { return left == null && right == null; } public HuffmanNode getLeft() { return left; } public HuffmanNode getRight() { return right; } @Override public int compareTo(HuffmanNode o) { return Integer.compare(this.frequency, o.frequency); } } } ``` 以上就是Huffman压缩解压缩文件的Java代码,您可以根据您的需要进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值