当前位置: 首页 > news >正文

从0开始打造自己的压缩软件(仅文字适配)上——文本的压缩

一、理清步骤首先作为一个程序我们必然是要一个输入的可能是个文本也可能是其他的内容。那么这个输入输出不能是像过去一样在终端中输入所以这里要引入我们的io流——即为我们的输入和输出的具体办法。然后我们要开始对文件进行压缩那么这里根据的要是什么标准呢因为我们输入的文本不同所以我们的编码方式一定要统一才行呀这里我们把每个字符都利用哈夫曼树进行可以编码从而达到压缩的目的。最后我们要做到把这个翻译出来再进行编译并输出就行了。二、着手进行压缩的部分1.读取首先先写一个读入的函数即传统意义上的输入。这里用到io包中的BufferedReader这个类。publicStringBuilderfileDatanewStringBuilder();StringpathE:\\input.txt;FilefnewFile(path);BufferedReaderbrnull;try{brnewBufferedReader(newFileReader(f));Stringline;while((linebr.readLine())!null){fileData.append(line).append(\r\n);}}catch(Exceptione){thrownewRuntimeException(e);}为了避免文件为空这里可以适用try-catch方法对相应的点进行抓取异常。然后可以加上其他的输出语句如果你需要。在这之后可以很轻松地看出来我们已将一个文件中的全部内容以一个Bufferreader 的形式将文件中的全部数据以一个fileData的读取器给取出来了while循环这里我们是将所有的内容以名为line 的字符串形式读取出来了所有的内容并把他们不断地拼接到起来直到我们没有了内容为止。到那时这还不是我们想要的结果因为现在它还是一个对象我们要不断地取出其中的字符并统计他们出现的频率这样才能搞出想要的结果。我待会说明。哈希表介绍联想到前次的哈希表解释不太全面我重新说一下——这里仅介绍相应的功能特点如需要一些更全面的代码获取请看我上次的文章哈希表和其他的小内容它有一点很好的效果就是在每次使用后面对相同的key值时可以不断地更新后面的value部分使得其能够被不断地使用并覆盖前面的value内容。在这里我们可以很好地使用并适配使得其能够作为一个统计器。现在我们就可以很好地 利用这一特性对每个字符进行统计了。HashMapString,IntegerhmnewHashMap();for(inti0;ifileData.length();i){charcfileData.charAt(i);//查找当前map中的是否存在keyif(hm.containsKey(c)){hm.put(c,hm.get(c)1);}else{hm.put(c,1);}}看到了吗我们通过不断地更新相应的value值将每一个char key都赋予了对应的value值体现了其一一对应的相关关系。2.建树接下来我们可以通过哈夫曼树对每个字符建树。不用担心这个新出现的数据结构。哈夫曼树介绍哈夫曼树是这样的对于一个数列来说不断地去取其中最小的两个数在这之后不断地进行对前两个数进行运算并把运算后的值重新放到数列中进行排列而后周而复始不断循环这样我们便可以得到一个将全部的数都变为一个树的全部叶子节点的树。接下来如果有根节点我们便可以轻松地知道每一个叶子节点的值。再接下来若使每一个节点都与其他节点区分开来我们可以从根节点开始给每一个分支进行编码比如将左儿子编码为0将右儿子编码为1重复此步骤直到所有的叶子节点都能拥有一连串的代表自己的编码。回到我们的应用上来这就可以作为一个例子既然我们需要将频率最高的目标标注出来我们就可以使用这个方法将目标进行相应的编码和使用从而出现每一个字符都有一一对应的相关的编码以字符串的方式进行存储该树即为我们将文件翻译成一连串编码的快捷密码本。for循环的另一个写法不过呢我们要先明了:for循环不是千古不变的一种写法forint i0;in;i{};如果语句需要变得简化我们可以这样写:for(i:n){}二者等效。现在我们先建一个树吧别忘了要先写一个TreeNode 的类不然我们没有根。classTreeNode{publicintdata;publicStringcode;publicStringstr;publicTreeNodeleft;publicTreeNoderight;publicTreeNode(){}publicTreeNode(intdata){this.datadata;}publicTreeNode(Stringstr,intdata){this.datadata;this.strstr;}}这样我们就可以在刚才的环境下建上另一个树了。for(Map.EntryString,Integerentry:hm.entrySet()){TreeNodenodenewTreeNode(entry.getKey(),entry.getValue());nodeList.add(node);这里是能够让每个字符都有能让他对应的节点。现在节点和树都有了链接就行了。publicvoidinOrder(){TreeNodecurrroot;StackTreeNodestacknewStack();while(curr!null||!stack.isEmpty()){if(curr!null){stack.push(curr);currcurr.left;}else{TreeNodenodestack.pop();currnode.right;}}}现在每个字符都已经有但是我们仍然要把他们和自己的编码链接起来让每一个字符都有自己的编码。publicvoidorder(TreeNoderoot,Stringcode){if(rootnull)return;if(root.leftnullroot.rightnull){root.codecode;System.out.println(root.str:root.code);h.put(root.str,root.code);}order(root.left,code0);order(root.right,code1);}既然我们已经有了对应的编码现在就更为方便了。要做的不过是把它从01编码压缩进行加密这是要把每八个01字符转换成一个10进制数字相应的笔记本反而会一各个地记录相应的数字对应的字符这样你的文字便会被加密没有密码本是无法看见的。publicvoidchuli(){intn(8-(g.length()%8))%8;intt0;Integerb0;charc;StringfnewString();Stringend;// char zg.charAt(0);// System.out.println(z);System.out.println();for(inti0;in;i){gg0;}//把g补完try{FileOutputStreamfosnewFileOutputStream(E:\\a.txt);ObjectOutputStreamoosnewObjectOutputStream(fos);oos.writeObject(h);oos.flush();for(inti0;ig.length();i){cg.charAt(i);ff(c);t;if(t8){System.out.println(ff);endendf;bInteger.parseInt(f,2);System.out.println(b);t0;f;fos.write(b);fos.flush();}}System.out.println(end);}catch(Exceptione){thrownewRuntimeException(e);}}好了有人可能注意到这里的不够8位的地方我全用的是0补齐这个地方看一下有个印象就好。本篇代码我放在下面了。packageHOLIDAY;importcom.sun.source.tree.Tree;importjava.sql.SQLOutput;importjava.util.*;importjava.io.*;publicclassHfmTree{publicTreeNoderoot;publicStringBuilderfileDatanewStringBuilder();HashMapString,IntegerhmnewHashMap();HashMapString,StringhnewHashMap();ListTreeNodenodeListnewLinkedList();Stringg;publicvoidread(){// String path D:\\IdeaProjects\\Java01\\src\\K\\Begin.java;0StringpathE:\\input.txt;FilefnewFile(path);BufferedReaderbrnull;try{brnewBufferedReader(newFileReader(f));Stringline;while((linebr.readLine())!null){fileData.append(line).append(\r\n);}}catch(Exceptione){thrownewRuntimeException(e);}System.out.println( fileData fileData.toString());//统计字符频率for(inti0;ifileData.length();i){charcfileData.charAt(i);//查找当前map中的是否存在keyif(hm.containsKey(c)){hm.put(c,hm.get(c)1);}else{hm.put(c,1);}}for(Map.EntryString,Integerentry:hm.entrySet()){TreeNodenodenewTreeNode(entry.getKey(),entry.getValue());nodeList.add(node);}//忘了干啥的了这步}publicvoidsort(ListTreeNodenodeList){for(inti0;inodeList.size();i){for(intj0;jnodeList.size()-1;j){if(nodeList.get(j).datanodeList.get(j1).data){TreeNodetempnodeList.get(j);nodeList.set(j,nodeList.get(j1));nodeList.set(j1,temp);}}}}publicvoidcreateTree(ListTreeNodenodeList){while(nodeList.size()1){sort(nodeList);TreeNodeleftnodeList.remove(0);TreeNoderightnodeList.remove(0);TreeNodenodenewTreeNode(left.dataright.data);node.leftleft;node.rightright;nodeList.add(node);}rootnodeList.remove(0);}publicvoidinOrder(){TreeNodecurrroot;StackTreeNodestacknewStack();while(curr!null||!stack.isEmpty()){if(curr!null){stack.push(curr);currcurr.left;}else{TreeNodenodestack.pop();currnode.right;}}}publicvoidorder(TreeNoderoot,Stringcode){if(rootnull)return;if(root.leftnullroot.rightnull){root.codecode;System.out.println(root.str:root.code);h.put(root.str,root.code);}order(root.left,code0);order(root.right,code1);}publicvoidda(){for(inti0;ifileData.length();i){charcfileData.charAt(i);ggh.get(c);}System.out.print(g);}publicvoidchuli(){intn(8-(g.length()%8))%8;intt0;Integerb0;charc;StringfnewString();Stringend;// char zg.charAt(0);// System.out.println(z);System.out.println();for(inti0;in;i){gg0;}//把g补完try{FileOutputStreamfosnewFileOutputStream(E:\\a.txt);ObjectOutputStreamoosnewObjectOutputStream(fos);oos.writeObject(h);oos.flush();for(inti0;ig.length();i){cg.charAt(i);ff(c);t;if(t8){System.out.println(ff);endendf;bInteger.parseInt(f,2);System.out.println(b);t0;f;fos.write(b);fos.flush();}}System.out.println(end);}catch(Exceptione){thrownewRuntimeException(e);}}publicstaticvoidmain(String[]args){HfmTreehfmnewHfmTree();hfm.read();hfm.createTree(hfm.nodeList);hfm.inOrder();hfm.order(hfm.root,);hfm.da();hfm.chuli();}}classTreeNode{publicintdata;publicStringcode;publicStringstr;publicTreeNodeleft;publicTreeNoderight;publicTreeNode(){}publicTreeNode(intdata){this.datadata;}publicTreeNode(Stringstr,intdata){this.datadata;this.strstr;}}//flie input.string
http://www.gsyq.cn/news/1374025.html

相关文章:

  • qemu和gcc编译
  • # 网页设计学习感悟
  • Claude Code 在安装vscode插件时遇到的问题。
  • 解锁UE5.1增强输入高级玩法:用自定义Input Modifier实现游戏摇杆灵敏度曲线与高级死区
  • Unity地形优化实战:Terrain设置、LOD与Draw Call控制,让你的开放世界跑得更流畅
  • 网络安全学习第112天
  • 2026国际传感器展会优质平台推荐:上海传感器展会、中国传感器展会、北京传感器展会、国际传感器展会、中国传感器展选择指南 - 优质品牌商家
  • 企业官网后台的工程化设计:内容建模、所见即所得与源码自主可控
  • 一文讲清楚规则、Skill、MCP
  • 别再手动下载DLL了!用Windows自带工具SFC/SCANNOW一键修复kernel32.dll错误
  • 2026年Q2,为何专业通信工程商纷纷锁定河北乐佳U型钢走线架? - 2026年企业推荐榜
  • 别再只用ARIMA了!用Python的SSA算法给你的时间序列数据‘卸个妆’(附完整代码与调参心得)
  • Bi-LSTM vs CNN-BiLSTM:实战对比哪个模型更适合你的时间序列预测任务?
  • 交通顶刊TR Part C 2026年6月论文导读(下)
  • AI应用开发岗面经
  • 别再让系统‘无家可归’:给已用满空间的Win10 SSD无损创建EFI引导分区指南
  • 别再只认ldd了!盘点5种查看Linux程序动态库依赖的方法(含静态/交叉编译场景)
  • 【程序源代码】答题微信小程序(含源码)
  • 2026年Q2长沙原木定制优选:深度解析逸林家具的硬实力与专业服务 - 2026年企业推荐榜
  • VMware升级后Ubuntu 22.04虚拟机网卡‘消失’?别慌,这6个命令帮你一键找回(附排查思路)
  • 不止是搜索!Listary隐藏玩法大揭秘:网页传文件、快速启动器、资源管理器增强
  • 别再乱装驱动了!Win10/Win11频繁蓝屏DPC_WATCHDOG_VIOLATION,用WinDBG揪出真凶(保姆级排查流程)
  • 告别虚拟机!手把手教你用U盘给新电脑装Win11+统信UOS 1060双系统(保姆级分区教程)
  • 别再乱拔网线了!在国产系统(UOS/KOS)里给网卡“软关机”的两种正确姿势
  • SAM(Segment Anything)实战:用Python+OpenCV把分割结果玩出花,不止是数据集
  • 别再一段段拼了!用UE4蓝图+Spline Component,一键生成连续管道/道路模型
  • 别再死记硬背区别了!用5个实际代码案例,带你吃透XLua和ToLua的核心用法差异
  • 保姆级教程:用Python处理Potsdam遥感数据集,从TIF到JPG/PNG再到模型训练
  • 超越基础用法:用Resources.Load动态加载UI Sprite,实现一个可配置的图片切换器(附完整C#脚本)
  • Drupal YAML反序列化RCE漏洞CVE-2017-6920深度解析