文件压缩和解压
来源:互联网 发布:手机淘宝怎么取消退款? 编辑:程序博客网 时间:2024/04/25 07:26
今天刚学完文件的压缩和解压,在老师的帮助下完成了这个小程序,感觉很有干劲,很充实,不想以前的暑假,不是在看小说就看视频,虽然一时感觉很愉悦,然而玩了以后就很无聊,觉得无所事事,下面是文件压缩和解压代码和大家分享一下。
文件压缩最重要的数据结构:哈夫曼二叉树(最优二叉树)
//构造哈夫曼二叉树结点:
package hmfTree;
public class HfmTreeNode implements Comparable<HfmTreeNode> {
private HfmTreeNode leftNode;
private HfmTreeNode rightNode;
private Integer times;
private Integer data;
public HfmTreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(HfmTreeNode leftNode) {
this.leftNode = leftNode;
}
public HfmTreeNode getRightNode() {
return rightNode;
}
public void setRightNode(HfmTreeNode rightNode) {
this.rightNode = rightNode;
}
public Integer getTimes() {
return times;
}
public void setTimes(Integer times) {
this.times = times;
}
//构造函数
public HfmTreeNode(Integer times , Integer data){
this.times=times;
this.data=data;
}
public Integer getData() {
return data;
}
public void setData(Integer data) {
this.data = data;
}
public int compareTo(HfmTreeNode o)
{
return times.compareTo(o.times);
}
// public String toString()
// {
// return "[" + times + "]";
// }
}
package hmfTree;
/*
* 压缩文件
*
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.PriorityQueue;
public class test {
//保存所有哈夫曼编码
String [] allCode=new String[256];
//保存所有字符个数
int[] allChar= new int[256];
PriorityQueue <HfmTreeNode> HfmList=new PriorityQueue<HfmTreeNode>();
public static void main(String[] args){
test t=new test();
//压缩过程
//获取所有字符的个数
t.CountChar("t.txt");
//构造Hfm树
HfmTreeNode root=t.CreateTree();
//生成所有字符的哈夫曼编码
t.CreateHfmDict(root,"");
//打印
for(int i=0;i<t.allCode.length;i++){
System.out.println(t.allCode[i]+"------"+i);
}
//写哈夫曼编码长度
t.WriteHfmCodeLength("t1.txt");
//获取哈夫曼编码
StringBuffer f=new StringBuffer("");
StringBuffer HfmCodeData=f.append(t.AppendHfmCodeData());
//获取文件数据
StringBuffer fileData= t.AppendFileDataByHfmCode("t.txt");
//哈夫曼编码加文件数据
StringBuffer HfmData=HfmCodeData.append(fileData);
System.out.println(HfmData);
//获取补零后的数据
StringBuffer HfmData1=t.AppendZero(HfmData);
System.out.println(HfmData1+"-----"+HfmData1.length());
//把压缩后的数据写入文件
t.WriteData("t1.txt", HfmData1);
}
//获取所有字符的个数
public void CountChar(String fileName){
//初始化allCode数组
for(int i=0;i<allCode.length;i++){
allCode[i]="";
}
try{
File file=new File(fileName);
//创建文件输出流
FileInputStream fis=new FileInputStream(file);
//包装成缓冲文件
BufferedInputStream bis=new BufferedInputStream(fis);
int i;
while ((i = bis.read()) != -1)
{
allChar[i]++;
}
//Arrays为操作数组的类
System.out.println(Arrays.toString(allChar));
//关闭输入流
bis.close();
}catch(IOException e){
e.printStackTrace();
System.out.println("此文件不存在!!!");
}
}
//构造Hfm树
public HfmTreeNode CreateTree(){
for(int i=0;i<256;i++){
if(allChar[i]!=0){
//加入Hfm树的子结点
HfmTreeNode node=new HfmTreeNode(allChar[i],i);
HfmList.add(node);
}
}
while(HfmList.size()!=1){
HfmTreeNode leftNode=HfmList.poll();
HfmTreeNode rightNode =HfmList.poll();
//得到新的父节点
Integer newtimes=leftNode.getTimes()+rightNode.getTimes();
HfmTreeNode newnode=new HfmTreeNode(newtimes,null);
HfmList.add(newnode);
//设置父节点的左右子结点
newnode.setLeftNode(leftNode);
newnode.setRightNode(rightNode);
}
HfmTreeNode root=HfmList.peek(); //哈夫曼树的根节点
return root;
}
//生成所有字符的哈夫曼编码
public void CreateHfmDict(HfmTreeNode node,String code){
//判断节点为叶子结点
if(node.getLeftNode()==null&&node.getRightNode()==null){
Integer data=node.getData();
allCode[data]=code;
}
//判断有左子结点
if(node.getLeftNode()!=null){
//递归调用
CreateHfmDict(node.getLeftNode(),code+"0");
}
//判断有右子结点
if(node.getRightNode()!=null){
//递归调用
CreateHfmDict(node.getRightNode(),code+"1");
}
}
//写哈夫曼编码长度
public void WriteHfmCodeLength(String fileName){
try{
File file1=new File(fileName);
//创建文件输出流
FileOutputStream fos=new FileOutputStream(file1);
//文件缓冲流
BufferedOutputStream bos=new BufferedOutputStream(fos);
for(int i=0;i<allCode.length;i++){
int l=allCode[i].length();
bos.write(l);
}
//关闭缓冲输出流
bos.flush();
bos.close();
}catch(IOException e){
e.getStackTrace();
System.out.println("文件不存在!!!");
}
}
//追加所有哈夫曼编码
public String AppendHfmCodeData(){
String s=Arrays.toString(allCode);
s=s.replace("[","");
s=s.replace(",", "");
s=s.replace(" ", "");
s=s.replace("]", "");
System.out.println(s);
return s;
}
//追加文件数据
public StringBuffer AppendFileDataByHfmCode(String fileName){
//可变字符串
StringBuffer fileData=new StringBuffer();
try{
File file=new File(fileName);
//创建文件输出流
FileInputStream fis=new FileInputStream(file);
//包装成缓冲文件
BufferedInputStream bis=new BufferedInputStream(fis);
int i;
while ((i = bis.read()) != -1)
{
//读文件中的数据,翻译为哈夫曼编码
String hfmCode=allCode[i];
//追加
fileData.append(hfmCode);
}
System.out.println(fileData);
bis.close();
}catch(IOException e){
e.getStackTrace();
System.out.println("文件不存在!!!");
}
finally{
return fileData;
}
}
//补零操作
public StringBuffer AppendZero( StringBuffer HfmData){
//计数器 记录补零的数量
int count=0;
while(HfmData.length()%8!=0){
HfmData=HfmData.append("0");
count++;
}
//将十进制数转化为二进制字符串
String countStr=Integer.toBinaryString(count);
//补零
while(countStr.length()<8){
countStr="0"+countStr;
}
//加入补零数字串
HfmData=HfmData.append(countStr);
return HfmData;
}
//写文件
public void WriteData(String fileName,StringBuffer HfmData){
try{
File file1=new File(fileName);
//创建文件输出流
FileOutputStream fos=new FileOutputStream(file1,true);
//文件缓冲流
BufferedOutputStream bos=new BufferedOutputStream(fos);
while(HfmData.length()!=0){
//截取HfmData[0,8)
String substring=HfmData.substring(0, 8);
//把截取串转化为十进制
int parseInt=Integer.parseInt(substring, 2);
System.out.println(parseInt);
//把十进制数写入文件
bos.write(parseInt);
//删除截取的HfmData
HfmData.delete(0,8);
}
//关闭缓冲输出流
bos.flush();
bos.close();
}catch(IOException e){
e.getStackTrace();
System.out.println("文件不存在!!!");
}
}
}
package hmfTree;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/*
* 解压文件
*
*/
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class test1 {
//保存所有字符个数
int[] charCount= new int[256];
Map<String ,Integer> keyCode=new HashMap<String ,Integer>();
public static void main(String[] args){
test1 t1=new test1();
//得到哈夫曼编码和文件数据
StringBuffer sb= t1.ReadHfmCodeLength("t1.txt");
t1.HandleZero(sb);
StringBuffer data=t1.GenrateHfmCodeMap(sb);
t1.WriteFileData("t3.txt", data);
}
//读取哈夫曼编码长度
public StringBuffer ReadHfmCodeLength(String fileName){
//可变字符串
StringBuffer sb=new StringBuffer("");
try{
File file=new File(fileName);
//文件输入流
FileInputStream fis=new FileInputStream(file);
BufferedInputStream bis=new BufferedInputStream(fis);
//读文件的前256位
int i;
//计数器
int count=0;
while(true){
if(count==256){
break;
}
//读取到第i个
i=bis.read();
//设置第i个哈夫曼编码的长度
charCount[count]=i;
count++;
}
//读哈夫曼编码和文件数据
while((i=bis.read())!=-1){
//将十进制转化为二进制串
String integerString =Integer.toBinaryString(i);
//在前补零
while(integerString.length()<8){
integerString="0"+integerString;
}
System.out.println(integerString);
//记录哈夫曼编码和文件数据 011100001111100000000010
sb=sb.append(integerString);
}
System.out.println(sb);
System.out.println(Arrays.toString(charCount));
bis.close();
}catch(IOException e){
e.getStackTrace();
}
return sb;
}
//消除补充的零
public StringBuffer HandleZero(StringBuffer sb){
// StringBuffer data=new StringBuffer();
//获取补零数值串
String subString=sb.substring(sb.length()-8, sb.length());
//转化为十进制
int zeroCount=Integer.parseInt(subString, 2);
System.out.println(zeroCount);
//删除补零数值串
sb.delete(sb.length()-8, sb.length());
//得到倒数第二串8位
String subString1=sb.substring(sb.length()-8, sb.length());
sb.delete(sb.length()-zeroCount, sb.length());
System.out.println(sb);
return sb;
}
//得到哈夫曼字典
public StringBuffer GenrateHfmCodeMap(StringBuffer sb){
for(int i=0;i<charCount.length;i++){
if(charCount[i]==0){
continue;
}
if(charCount[i]!=0){
//截取charCount[i]个
String HfmCodeString=sb.substring(0, charCount[i]);
//加入Map内
keyCode.put(HfmCodeString, i);
sb.delete(0, charCount[i]);
}
}
System.out.println(keyCode);
System.out.println(sb);
return sb;
}
//写文件数据
public void WriteFileData(String fileName,StringBuffer data){
try{
File file1=new File(fileName);
//创建文件输出流
FileOutputStream fos=new FileOutputStream(file1);
//文件缓冲流
BufferedOutputStream bos=new BufferedOutputStream(fos);
//不包含key
while((data.length())!=0){
int i=1;
String key="";
key=data.substring(0, i);
while(!keyCode.containsKey(key)){
i++;
key=data.substring(0, i);
}
//包含key
bos.write(keyCode.get(key));
data.delete(0, i);
}
//关闭缓冲输出流
bos.flush();
bos.close();
}catch(IOException e){
e.getStackTrace();
System.out.println("文件不存在!!!");
}
}
}
总结:文件压缩最主要的是清楚的了解文件压缩的步骤,知道文件的io流中的怎样读文件和写文件和怎样操作二叉树,解决这三个问题,文件的压缩就几乎完成了;而解压缩是文件压缩的逆过程,清楚了文件的压缩过程文件的解压就不成问题了,具体过程就看下代码吧。
- 压缩和解压文件
- 文件压缩和解压
- 文件压缩和解压
- 文件的压缩和解压
- Linux文件压缩和解压
- Zlib文件压缩和解压
- Zlib文件压缩和解压
- LINUX文件压缩和解压
- Android 文件压缩和解压
- .net 文件压缩和解压
- Android_JarZip压缩和解压文件
- Android文件压缩和解压
- linux 压缩和解压文件
- Linux 文件压缩和解压
- Zlib文件压缩和解压
- java压缩和解压文件
- ant压缩和解压文件
- 文件压缩和解压zip
- String转成字符串数组
- java io流管道流
- 数组与指针的区别
- leetcode 028 —— Implement strStr()
- 新建phonegap工程
- 文件压缩和解压
- hdu 1865 1sting
- cxf(3.1.1) 客户端异常 请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。
- 暴力枚举 C. Arthur and Table
- 【计蒜客系列】挑战难题9:元素移除
- hdu4185最大二分匹配
- 史上最全的程序员求职渠道总结
- C++常用术语及其英文翻译的含义和简单用途总结(一)
- Broken Keyboard(hash)