继续前文"哈夫曼压缩与解压缩学习笔记(一)"
http://128kj.iteye.com/blog/1706760
(3)BitOutputStream.java
这个类用于写压缩文件,主要方法writeBits(int[] val)用于将某一个字节的哈夫曼编码val写入文件,写的时候是一位一位先写入缓存区(写的顺序是先写缓存区的低位,后到高位),只有满八位时才flush()真正写入,如果没有八位,从下一字节中读入。
例:上面提到的文件"ASCTASCTAAAAACCTTT",共有18个字符,压缩写时先写第一个字符A,其哈夫曼编码只有一位0,先将0写入缓存区buffer的最低位,buffer=0,再写第二个字符S,一位一位的写,其哈夫曼编码为111,此时缓存区buffer=1110,然后...如下表所示:
字符写入次序 哈夫曼编码 缓冲区buffer的二进制表示
(1)A 0 0
(2)S 111 1110
(3)C 110 0111110
(4)T 10 0 (当buffer=10111110时,清空缓存写入
out,T的编码10中的1已写入,0仍在缓存中)
(5)A 0 00
(6)S 111 11100
(7)C 110 01111100(缓存满,这是第二次写入的数据)
(8)T 10 01
(9)A 0 001
(10)A 0 0001
(11)A 0 00001
(12)A 0 000001
(13)A 0 0000001(已有七位)
(14)C 110 01(buffer=10000001缓存满,这是第三次写入的数据)
(15)C 110 01101
(16)T 10 0101101(已有七位)
(17)T 10 0 (buffer=10101101缓存满,这是第四次写入的数据)
(18)T 10 010 最后写入的数据
这样向压缩文件写入的字节数据是: 10111110 01111100 10000001 10101101 010
import java.io.*;
public class BitOutputStream {
private OutputStream out;
private int buffer;//向输出流out中写一位(bit)数据时,先写入此缓存区,只有满八位时才flush()真正写入out
private int bufferPos;//缓存区是否满的标志
public BitOutputStream( OutputStream os )
{
bufferPos = 0;
buffer = 0;
out = os;
}
public void writeBit( int val ) throws IOException//向缓存区写一位数据val,取0或1
{
buffer = setBit(buffer, bufferPos++, val );//将数据写入缓存区
if( bufferPos == BitUtils.BITS_PER_BYTES )//缓存区满时,清空并写入out文件
flush( );
}
public void writeBits(int [] val) throws IOException//将用数组表示的哈夫曼编码val写入文件
{
for( int v : val )
writeBit( v );
}
public void flush( ) throws IOException
{
if( bufferPos == 0 )
return;
// System.out.println(Integer.toBinaryString(buffer));
out.write( buffer );
bufferPos = 0;//缓存区标志复位
buffer = 0; //缓存区清空
}
public void close( ) throws IOException//关闭文件时,要将缓存区的数据写入文件一次
{
flush( );
out.close( );
}
private int setBit( int pack, int pos, int val )//将pack的第pos位的值设置为1
{
// System.out.println("pack="+pack+" pos="+pos+" val="+val);
// System.out.println();
if( val == 1 )
pack |= ( val << pos );//将pack的第pos位的值设置为1
return pack;
}
public static void main(String args[]) throws IOException{
int[] a={0,0};
int[] b={1,1,0};
int[] c={1,1,1};
int[] d={1,0};
int[] e={0,1,0,0,1};
BitOutputStream bo=new BitOutputStream(new FileOutputStream("d:\\java\\1.txt",true));
bo.writeBits(a);
bo.writeBits(b);
bo.writeBits(c);
bo.writeBits(d);
bo.writeBits(e);
bo.close();
}
}
(4)BitInputStream.java
此类用于解压缩,主要方法readBit()从缓存区中读一位数据,缓存区低位数据先读,高位后读,当缓存区的数据读完时,再从in中读一字节放入缓存区,如何解压缩?先要从压缩文件中读出码表(字节---频率)数据,并构建哈夫曼树,然后如下进行。
例:对于先前写入压缩文件中字节数据:10111110 01111100 10000001 10101101 010,解压过程度是这样的:
(1)先读取一字节数据10111110,放入缓存buffer中,读出它的最低位数据0,然后遍历哈夫曼树,从根节点往下找左子节点,发现0正好对应节点A;
(2)再从缓存buffer中读次低位数据1,又从哈夫曼树的根节点开始找叶子节点,1就从右找,0就左找,如果没有到叶子,再从缓存buffer中读
一位数据1,还没有到叶子节点,再读一位,这样读三位111后,就找到了对应的S,
(3)再从缓存中一位一位读三次,由110从哈夫曼树中找到C
(4)这时缓存buffer中只有一位数据1可读了,读完后再从in中读一字节01111100放入缓存,这时缓存又有数据可读了,读它的最低位0,由10从哈夫曼树中找到T,再下一步找到A,S,C,T,A,A,A,A,A,C,C,T,T,T,这样可由字节数据10111110 01111100 10000001 10101101 010 还原文件"ASCTASCTAAAAACCTTT"。
import java.io.*;
public class BitInputStream {
private InputStream in;//文件输入流
private int buffer;//八位的缓存区,从in读入的一个字节数据先放在这里
private int bufferPos;//缓存区标志
public BitInputStream( InputStream is )
{
in = is;
bufferPos = BitUtils.BITS_PER_BYTES;
}
//从缓存区中读一位数据,缓存区低位数据先读,高位后读,当缓存区的数据读完时,再从in中读一字节放入缓存区
public int readBit( ) throws IOException
{
if ( bufferPos == BitUtils.BITS_PER_BYTES )
{
buffer = in.read( );//从输入流中读一个字节
// System.out.println(Integer.toBinaryString(buffer));
if( buffer == -1 )
return -1;
bufferPos = 0;
}
// System.out.println("buffer="+buffer);
return getBit( buffer, bufferPos++ );
}
public void close( ) throws IOException
{
in.close( );
}
private static int getBit( int pack, int pos )//获取pack的二进制表示中的第pos位上的数值.
{
return ( pack & ( 1 << pos ) ) != 0 ? 1 : 0;
}
public static void main(String args[]) throws IOException{
FileInputStream is=new FileInputStream("d:\\java\\1.txt");
BitInputStream bi=new BitInputStream(is);
while(true){
int b=bi.readBit();
if(b==-1) break;
System.out.print(b+" ");
}
}
}
末完待续。。。。。。
分享到:
相关推荐
哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩...
哈夫曼实现文件的压缩与解压缩,代码关键部分有注释。
总之,哈夫曼压缩解压缩是数据压缩领域的一个重要方法,通过MFC和VC++,我们可以构建出直观且高效的压缩工具,便于学习和研究。在这个过程中,理解哈夫曼编码的原理、掌握MFC的使用以及实现压缩和解压缩的算法,都是...
在Java编程环境中实现哈夫曼压缩与解压缩程序,我们可以利用面向对象的特性,设计多个类来完成不同部分的功能。 1. **FileChooserDemo.java**:这是一个用户界面类,通常包含用于让用户选择输入和输出文件的控件。...
为了解压缩时重建哈夫曼树,压缩文件需要保存编码信息,包括ASCII值和对应的位序列。 解压缩阶段相对简单,从输入缓冲区中读取已编码的位流,然后遍历位流,根据哈夫曼树的结构寻找对应的叶节点,即字符的ASC II码...
哈夫曼解压缩程序,通常被称为Szip,是一种基于哈夫曼编码的高效数据压缩算法。在信息技术领域,数据压缩是存储和传输信息的关键技术,它通过减少数据冗余来节省存储空间和提高传输效率。哈夫曼编码是数据压缩中的...
哈夫曼编码是一种高效的数据压缩方法,它基于字符出现频率构建最优的二叉树结构,从而实现数据的压缩与解压缩。本文将深入探讨哈夫曼编码的原理,并通过一个使用C++编写的哈夫曼编码压缩解压缩程序,来阐述其具体...
5. **解压缩**:在解压缩阶段,从二进制序列开始,按照哈夫曼树的结构进行反向操作。每当遇到0时,向左移动;遇到1时,向右移动。当到达叶子节点时,读取该节点的字符,并输出。然后返回到根节点,继续解码剩余的二...
- 解压缩时,首先根据编码表或树结构重建哈夫曼树,然后利用`BitInputStream`读取二进制串,按照编码表还原文本。 6. **文件操作**: - 在实际应用中,哈夫曼编码的压缩结果需要写入文件。Java提供了`...
哈夫曼编码是一种高效的数据压缩方法,由大卫·哈夫曼在1952年提出。它是基于频率的变字长编码...通过阅读和分析提供的源代码,你可以更直观地了解哈夫曼编码的工作原理,并可能从中学习到如何优化和改进数据压缩算法。
在“利用哈夫曼原理的压缩解压缩软件”中,哈夫曼编码被应用于文件的压缩与解压缩过程。 MFC(Microsoft Foundation Classes)是微软开发的一种C++库,用于构建Windows应用程序。它提供了丰富的类结构,使得开发者...
这是哈夫曼压缩与解压缩的全套代码和需要的txt文件,huffman,tree
在C语言中实现哈夫曼编码的压缩与解压缩,涉及到的主要知识点包括以下几个方面: 1. **哈夫曼树的构建**:哈夫曼树是一种带权路径长度最短的二叉树。构建过程通常采用贪心策略,通过合并频率最小的两个节点来逐步...
哈夫曼编码是一种高效的数据编码方法,主要用于无损数据压缩。在信息技术领域,尤其是...通过C语言实现哈夫曼编码的压缩与解压缩,有助于理解数据压缩的基本原理,并为进一步学习和开发更高级的压缩算法奠定基础。
在“基于哈夫曼编码的文本文件压缩与解压缩.zip”这个压缩包中,很可能包含了用于演示或教学目的的哈夫曼编码实现代码、压缩和解压缩的示例文本以及相应的结果文件。学习和理解这个压缩包的内容,可以帮助我们更好地...
- 解压缩的过程与压缩相反。首先需要重建哈夫曼树,然后按照编码流逐位解析,根据哈夫曼树的结构确定每个编码对应的字符,从而还原出原始数据。 5. **Java实现** - 在Java中,可以使用`PriorityQueue`来实现最小...
在这个课程设计中,你将深入理解哈夫曼编码的原理,并通过C++编程语言实现文件的压缩与解压功能。 哈夫曼编码的核心思想是根据字符出现的频率来构建一个特殊的二叉树。在这个树中,频率较高的字符会被放在较近的叶...
vc++哈夫曼压缩算法 vc++哈夫曼压缩算法
在本项目“基于哈夫曼树的文件压缩与解压缩”中,开发者利用Python实现了对doc和txt文件的压缩与解压缩功能,确保了原始文件在解压后能完全恢复,不造成任何信息失真。 哈夫曼编码的基本原理是通过构建一个特殊的...
在C++中实现哈夫曼树压缩与解压涉及到几个主要步骤,包括构建哈夫曼树、生成哈夫曼编码、编码数据以及解码数据。 1. **哈夫曼树的构建** - 首先,统计输入文本中每个字符出现的频率,形成一个频率列表。 - 接着,...