- 浏览: 40243 次
- 性别:
- 来自: 长沙
文章分类
最新评论
在过年之前,先总结一下,自己第一次写的,漏洞百出的压缩。
相对来说,Huffman压缩的流程比较多。
压缩步骤:
1.读取原文件。
2.统计文件中每个字节出现的次数,存于Map<Byte, Integer>中。
3.根据每个字节的次数,构建Huffman树,得到每个字节对应的编码,存于Map<Byte,String>中。
4.根据Map<Byte, String>,将原文件的字节转化成0、1码。
5.将步骤4中得到的0、1码,每8位转换成一位十进制字节。最后0、1剩余不足8位时,则通过补0补满8位。在末尾添加一位,说明最后一位十进制对应的0、1二进制,实际有几位。
6.将Map<Byte, String>和步骤5得到的字节,写入文件中,得到压缩文件。
解压缩:
1.读压缩文件,先读取Map< String, Byte >,再读取压缩的源文件。
2.将压缩的源文件转换为0、1二进制。
3.根据Map< String, Byte >,将0、1二进制转换为对应的字节。
4.将步骤4得到的字节写入文件,即解压后的文件。
解压缩等同于顺序相反地执行压缩。
本程序的缺陷(只能压缩100k以内的文件,否则速度特别慢):
1.处理字节数组,这对大容量文件来说,肯定会数组越界。
解决方法:避免将内容全部存于数组来处理。
压缩:
1.1读文件时,读两遍。第一遍,得到Map<字节,出现的次数>。
1.2第二遍读原文件,读一个字节,根据Huffman得到的Map<字节,对应编码>,转换成0、1编码,满8位0、1码就转换为一个字节,写入压缩文件。
解压缩:
1.3读压缩文件的一个字节,转换为8位0、1码,根据Map<对应编码, 字节>,查找是否有对应的字节,若有,则写入解压的目标文件。再继续读压缩文件的一个字节,转换为8位0、1码,重复,直至读完压缩文件,并全部转化为字节,写入解压的文件。
2.未优化其中的函数模块,所以压缩速度比较慢。
如String可以用StringBuffer代替。虽然String的’+’用起来很方便,但是每’+’一个字符,虚拟机都new了一个String对象,释放原来的String对象,所以,’+’操作频繁,则效率很低。
有以下几点体会:
1.由于流程较多,所以,保证每个函数模块正确后,再将他们拼接起来,否则,找错误会很困难,不知道错在哪一部分。
函数可分为3部分:
(1).输入的参数
(2).函数实现
(3).输出结果
2.函数的参数,不要轻易地定义为类的属性。
虽然函数不需要传参,似乎方便了。但是,当类的属性名很多的时候,局部变量名易与类的属性同名,两者混淆;属性多了,容易忘记属性的具体意义。并且,函数的参数定义为类的属性,则一直占用空间。
所以,尽量作为函数参数传入,而不是简单地定义为类的属性。
3.byte类型的范围为:-128~127
而无符号的byte范围为:0~255,最大值为255。
当值大于127时,byte会从-128 ~ 127 ~ -128 ~ 127……在这256个数内循环。即128对应的byte为-128;129对应byte为-127。
所以,读文件时,可用readUnsignedByte();,当数字大于255时,则不能用byte了。否则结果错误。比如表示字节个数,就不能用byte类型表示,因为有256种字节。
5.文件的保存形式。
此处用的是字节流。若写入文件的内容由多个不同长度的部分组成,则可以在每个部分之前,用一个长度来表示这个部分的结束,来区分标志各个部分。
还有一种加分隔符,XML应该也是一种加入分隔符的形式。
6.测试函数执行所用的时间,来比较多种方案的效率
以下是代码,没有界面:
相对来说,Huffman压缩的流程比较多。
压缩步骤:
1.读取原文件。
2.统计文件中每个字节出现的次数,存于Map<Byte, Integer>中。
3.根据每个字节的次数,构建Huffman树,得到每个字节对应的编码,存于Map<Byte,String>中。
4.根据Map<Byte, String>,将原文件的字节转化成0、1码。
5.将步骤4中得到的0、1码,每8位转换成一位十进制字节。最后0、1剩余不足8位时,则通过补0补满8位。在末尾添加一位,说明最后一位十进制对应的0、1二进制,实际有几位。
6.将Map<Byte, String>和步骤5得到的字节,写入文件中,得到压缩文件。
解压缩:
1.读压缩文件,先读取Map< String, Byte >,再读取压缩的源文件。
2.将压缩的源文件转换为0、1二进制。
3.根据Map< String, Byte >,将0、1二进制转换为对应的字节。
4.将步骤4得到的字节写入文件,即解压后的文件。
解压缩等同于顺序相反地执行压缩。
本程序的缺陷(只能压缩100k以内的文件,否则速度特别慢):
1.处理字节数组,这对大容量文件来说,肯定会数组越界。
解决方法:避免将内容全部存于数组来处理。
压缩:
1.1读文件时,读两遍。第一遍,得到Map<字节,出现的次数>。
1.2第二遍读原文件,读一个字节,根据Huffman得到的Map<字节,对应编码>,转换成0、1编码,满8位0、1码就转换为一个字节,写入压缩文件。
解压缩:
1.3读压缩文件的一个字节,转换为8位0、1码,根据Map<对应编码, 字节>,查找是否有对应的字节,若有,则写入解压的目标文件。再继续读压缩文件的一个字节,转换为8位0、1码,重复,直至读完压缩文件,并全部转化为字节,写入解压的文件。
2.未优化其中的函数模块,所以压缩速度比较慢。
如String可以用StringBuffer代替。虽然String的’+’用起来很方便,但是每’+’一个字符,虚拟机都new了一个String对象,释放原来的String对象,所以,’+’操作频繁,则效率很低。
有以下几点体会:
1.由于流程较多,所以,保证每个函数模块正确后,再将他们拼接起来,否则,找错误会很困难,不知道错在哪一部分。
函数可分为3部分:
(1).输入的参数
(2).函数实现
(3).输出结果
2.函数的参数,不要轻易地定义为类的属性。
虽然函数不需要传参,似乎方便了。但是,当类的属性名很多的时候,局部变量名易与类的属性同名,两者混淆;属性多了,容易忘记属性的具体意义。并且,函数的参数定义为类的属性,则一直占用空间。
所以,尽量作为函数参数传入,而不是简单地定义为类的属性。
3.byte类型的范围为:-128~127
而无符号的byte范围为:0~255,最大值为255。
当值大于127时,byte会从-128 ~ 127 ~ -128 ~ 127……在这256个数内循环。即128对应的byte为-128;129对应byte为-127。
所以,读文件时,可用readUnsignedByte();,当数字大于255时,则不能用byte了。否则结果错误。比如表示字节个数,就不能用byte类型表示,因为有256种字节。
5.文件的保存形式。
此处用的是字节流。若写入文件的内容由多个不同长度的部分组成,则可以在每个部分之前,用一个长度来表示这个部分的结束,来区分标志各个部分。
还有一种加分隔符,XML应该也是一种加入分隔符的形式。
6.测试函数执行所用的时间,来比较多种方案的效率
long t1 = System.currentTimeMillis(); rd.mainly(); long t2 = System.currentTimeMillis(); long a = t2-t1;//计算rd.mainly();运行的时间 System.out.println("共用时"+a+"m秒");
以下是代码,没有界面:
package treeV2; //实现压缩、解压 public class Reduction { public static void main(String args[]){ Reduction rd=new Reduction(); long t1 = System.currentTimeMillis(); rd.mainly(); long t2 = System.currentTimeMillis(); long a = t2-t1;//计算rd.mainly();运行的时间 System.out.println("共用时"+a+"m秒"); } //总函数 public void mainly(){ //1.读源文件 FileTest file=new FileTest(); String sourcePath = "E:\\test.doc"; byte[] bytFile=file.readFile(sourcePath);//读原文件,得到的文件字节数组 System.out.print("读源文件的字节为:"); for(int i=0;i<bytFile.length;i++) System.out.print(bytFile[i]); System.out.println(); // 2.根据传入的字节,统计每个字节出现的次数 MapTest mt = new MapTest(); java.util.Map<Byte, Integer> mapBI = mt.createMap(bytFile); mt.mapToArraylist(mapBI);//取出map中数据,并存入 mapV //3.通过map<字节,次数>,建造Huffman树 Tree tree=new Tree(); tree.codeTree(tree.Array2Tree(MapTest.mapV)); //3.1转化成<字节、对应编码>的map java.util.Map<Byte, String> mapBS=mapOfCode(); System.out.println("写入压缩文件前的map<字节、对应编码>:"); // printMap(mapBS);//测试 //4.将原文件的字节转化成01码 String strBinary=byte2binary(bytFile,mapBS); System.out.println("将原文件的字节转化成01码:成功"); byte[] byt1=binary2byte(strBinary);//4.1 将01码转化成写入压缩文件的字节 System.out.println("压缩后的字节数组:"); for(int i=0;i<byt1.length;i++)//测试最后压缩后的原文件 System.out.print(byt1[i]+" "); System.out.println(); //System.out.println("map字节的总个数="+MapTest.mapV.size());//测试map字节的总个数 //5.将压缩文件的字节 写入压缩文件 String yasuoPath="E:\\aa.s";//压缩文件的路径 file.reduceWrite(yasuoPath, mapBS, byt1); System.out.println("----------------------读压缩文件后--------------------------:"); //6.读压缩文件,存入字节数组,得到map<01编码,字节> byte[] bytLast=file.reduceRead(yasuoPath);//解压缩后的文件字节 System.out.println("读压缩文件的map<编码、对应字节>:"); printMap1(file.mapLast);//测试读压缩后的map System.out.println("读压缩文件的原文件字节:");//测试读压缩后的原文件字节 for(int i=0;i<bytLast.length;i++){ System.out.print(bytLast[i]+" "); } System.out.println(); //7.转换成解压缩后的01文件 String strLast=recovery2binary(file.mapLast,bytLast);//解压缩后的01文件 System.out.print("读压缩文件的原文件01码:"+strLast); System.out.println("读压缩文件的原文件01码"); //8.通过map将01转成原文件字节,并写成原文件 recovery2file(file.mapLast,strLast, "E:\\test1.doc"); } //----------------------------文件压缩函数-------------------- /** * 1.将读文件的字节转为二进制0、1 * @param byt:读文件的字节 * @param map1:存<字节,编码> * @return:byte转化成string */ public String byte2binary(byte[] byt,java.util.Map<Byte, String> map1){ String str=""; for(int i=0;i<byt.length;i++){ str+=map1.get(byt[i]); //可再用二分搜索写一下 } System.out.println(" byte2binary转换后的01串为"+str+"长度为"+str.length()); return str; } //1.1转化 为map<字节、对应编码> //为了文件中字节转换为01编码方便,用到map的get方法 public java.util.Map<Byte, String> mapOfCode(){ java.util.Map<Byte, String> map=new java.util.HashMap<Byte, String>(); for(int i=0;i<MapTest.mapV.size();i++){ map.put(MapTest.mapV.get(i).keyB, MapTest.mapV.get(i).code);//存入字节,对应的编码 } return map; } /** * 2.将二进制0、1转换为十进制字节 * @param str:需要转换成字节的01码 * @return:压缩文件byte数组 */ public byte[] binary2byte(String str){ char[] str1=str.toCharArray(); int result=str1.length%8; byte[] byt1=new byte[str1.length/8+2];//若所有字节正好8位,则最后两位都为0 int k=0,i=0; //System.out.println(str1.length/8); for(;i<str1.length/8;i++){//有i个8 k=k+8; byte sum=0; for(int j=0;j<8;j++){ if(str1[k-j-1]!='0'){//字符直接乘错误 sum+=java.lang.Math.pow(2,j); } } byt1[i]=sum; } if(result!=0){//剩余位 byte sum=0; for(int j=0;j<result;j++){ if(str1[str1.length-1-j]!='0'){ sum+=java.lang.Math.pow(2,8-result+j); } } byt1[i]=sum; byt1[++i]=(byte)(result);//有result个0(result<8) //System.out.println("<<<<"+sum); }else{//无剩余位,则补两位0 byt1[i]=0; byt1[++i]=0; } return byt1; } //----------------------------文件解压缩的函数-------------------- /** * 1.1将字节转为对应0、1编码,1位十进制转为8位二进制, * @param b:需要转换的字节 * @return 字符串 */ public String dec2binary(byte b){//可直接转成整型,若为字节,则范围-128~127.无法表示128~255,所以用整型运算 int a; if(b<0)//计算成为正确的整型 a=b+256; else a=b; String str=""; int i=0; int d=128;//除数 while(i<8){ int ay=a/d;//当不足8位时,此处可改为:不需计算直接剩余赋为0 //System.out.print(" "+ay); if(ay==0) str+='0'; else{ a=a-d; str+='1'; } d=d/2; i++; } return str; } /** * 1.2将文件字节数组转为01编码 * @param map:<编码,字节> * @param b: 需要转换的字节数组 * @return */ public String recovery2binary(java.util.Map<String, Byte> map,byte[] b){ String str=""; for(int i=0;i<b.length-2;i++){ str+=dec2binary(b[i]);//将字节转换为01 } //最后两位处理 if(b[b.length-1]!=0){//有不足8位的 String str1=dec2binary(b[b.length-2]);//将最后第二位译成01码 //取str1前b[b.length-1]位 str+=str1.substring(0, b[b.length-1]); } return str; } /** * 2.将解压的01编码翻译成原文件,写入指定目录 * @param map:读压缩文件的map * @param str:要转换的01码 * @param filePath:解压的文件路径 */ public void recovery2file(java.util.Map<String, Byte>map,String str,String filePath){ String strtest="";//测试转换后的文件字节 java.util.Set<String> keys=map.keySet();//建立 Map的Set集合 //得到Set的迭代器,遍历Set java.util.Iterator<String> iterator=keys.iterator(); int n=MapTest.mapV.size();//总字节个数 String[] s=new String[n]; int i=0; //将iterator中编码存于数组String[]中 while(iterator.hasNext()){//iterator仍有元素迭代 s[i]=iterator.next(); i++; } //创建指定路径的文件对象 java.io.File file=new java.io.File(filePath); try{ //创建这个文件的输出流 java.io.FileOutputStream fos=new java.io.FileOutputStream(file); while(!str.isEmpty()){//str为空 for(int j=0;j<s.length;j++){//从第一个开始找,所以不能用contains i=0; while(i<s[j].length() && str.charAt(i)==s[j].charAt(i) ){//包含s[j] i++; } if(i==s[j].length()){ // System.out.println("recovery2files[j]为:"+s[j]); byte b=map.get(s[j]); //得到相应字节 //将字节b写入制定文件 fos.write(b); str=str.substring(s[j].length(), str.length());//不考虑效率,每次new一个string strtest+=b; break; } } } //强制输出 fos.flush(); fos.close(); }catch(Exception ef){ ef.printStackTrace(); } System.out.println("recovery2file测试后结果为:"+strtest); } //测试打印java.util.Map<Byte, String> public void printMap(java.util.Map<Byte, String> map){ //建立 Map的Set集合 java.util.Set<Byte> keys=map.keySet(); //得到Set的迭代器,遍历Set java.util.Iterator<Byte> iterator=keys.iterator(); while(iterator.hasNext()){//仍有元素迭代 byte b=iterator.next(); //根据key得到相应的value String code=map.get(b); System.out.println(code+"<<---"+b);//输出map中的key和value } } //测试打印java.util.Map<String, Byte> public void printMap1(java.util.Map<String, Byte> map){ //建立 Map的Set集合 java.util.Set<String> keys=map.keySet(); //得到Set的迭代器,遍历Set java.util.Iterator<String> iterator=keys.iterator(); while(iterator.hasNext()){//仍有元素迭代 String code=iterator.next(); //根据key得到相应的value byte b=map.get(code); System.out.println(code+"--->>"+b);//输出map中的key和value } } }
package treeV2; //1.读取原文件 //2.编码01二进制转换成十进制,由字节形式写入文件, //3.读取文件,将字节转换为二进制,再解码 public class FileTest { java.util.Map<String, Byte> mapLast=new java.util.HashMap<String, Byte>();//存读入的map //首先,读取将要压缩的文件 public byte[] readFile(String str){ //创建对应路径的文件,由于有try{}catch,所以不判断文件是否存在也可以 java.io.File file=new java.io.File(str); //如果文件存在 if(file.exists()){ try{ //创建文件对象的输入流 java.io.FileInputStream fis=new java.io.FileInputStream(file); //得到输入流的字节 int len=fis.available(); //创建字节数组,存放读入的字节 byte by[]=new byte[len]; int t=fis.read();//读完文件,t=-1 int i=0; while(t!=-1){ by[i]=(byte)t;//int 转为 byte t=fis.read(); i++; } fis.close();//关闭文件 return by; }catch(Exception ef){ ef.printStackTrace(); } } return null; } /** * 读取指定路径,并解压 * @param path:读取压缩文件的路径 * @return:压缩文件的字节数组 */ public byte[] reduceRead(String path){ byte[] bytt = null;//存放文件压缩的字节数组 //创建文件对象 java.io.File file=new java.io.File(path); //如果文件存在 if(file.exists()){ try{ //创建这个文件的输入流 java.io.FileInputStream fis=new java.io.FileInputStream(file); //将问件输入流包装成课读基本类型的数据流 java.io.DataInputStream dis=new java.io.DataInputStream(fis); //1.先读取map中字节个数 int num=dis.readShort();//可能有256个字节,所以用int写,不能用byte System.out.println("读文件map中字节个数为"+num); //2.读取map for(int i=0;i<num;i++){ byte byt=dis.readByte();//(1)读字节 //(2)读对应编码长度,转换成String int codeLen=dis.readUnsignedByte();//次数>127,无符号byte String str=""; for(int j=0;j<codeLen;j++){//(3)读编码 int t=fis.read(); str+=(char)t;//直接将int转为01字符 ///int转为char: 转换成int值对应的ASCII码 } mapLast.put(str,byt ); //装入<01编码、字节> } //3.读存入的文件压缩字节 int len=fis.available();//剩余字节长度 //给bytt定义空间,存放文件压缩的字节 bytt=new byte[len]; int t=fis.read(); int i=0; while(t!=-1){ bytt[i]=(byte)t; t=fis.read(); i++; } System.out.println("读的原压缩文件为");//测试输出所读文件的压缩字码段 for(int j=0;j<bytt.length;j++) System.out.print(bytt[j]+" "); System.out.println(); }catch(Exception ef){ ef.printStackTrace(); } } return bytt; } /** * 将map和转换后的字节数组写入指定的地址 * @param path压缩文件地址 * @param map<字节,对应01编码> * @param bytt转换后的文件字节 */ public void reduceWrite(String path,java.util.Map<Byte, String> map,byte[] bytt){ try{ //文件输出流 java.io.FileOutputStream fos=new java.io.FileOutputStream(path); //将文件流包装成数据输出流 java.io.DataOutputStream dos=new java.io.DataOutputStream(fos); //1.写入map中字节的个数 dos.writeShort(MapTest.mapV.size()); //可能有256个字节,所以用int写,不能用byte System.out.println("写文件map中字节个数为"+MapTest.mapV.size()); //2.写入map中数据 for(int i=0;i<MapTest.mapV.size();i++){ dos.writeByte(MapTest.mapV.get(i).keyB);// (1)写字节 //(2)写字节对应编码长度 dos.writeByte(MapTest.mapV.get(i).code.length()); //(3)写编码 byte by[]=MapTest.mapV.get(i).code.getBytes(); fos.write(by);//将字节数组写到文件 //char 转为 byte:得到对应ASCII的int值 } //3.写入转换后的原文件压缩字节 fos.write(bytt); //强制输出 fos.flush(); fos.close(); }catch(Exception ef){ ef.printStackTrace(); } } }
package treeV2; public class MapValue { public byte keyB;// 存读取文件的字符 public int times;// 次数 String code; //对应的二进制编码 }
package treeV2; public class Tree { private int n=0;//outArray(TreeNode a[])中限制大小 /** * 将指定的数组转化成哈夫曼树 * @param arr:要转化的数组 * @return:将转化后的树的根节点返回 */ public TreeNode Array2Tree(java.util.ArrayList<MapValue> mapVL){ bubbleOrder(mapVL);//先按次数排序 n=mapVL.size();//比较大小的数组的长度 //另外写一个方法求得数组内的实际元素个数 int m=2*mapVL.size()-1;//共2n-1个节点 TreeNode nodes[]=new TreeNode[m];//创建节点数组,其中只存比较大小的节点 for(int i=0;i<mapVL.size();i++){//创建n个叶子节点,并初始化 TreeNode node=new TreeNode(mapVL.get(i).times,mapVL.get(i).keyB); nodes[i]=node; } for(int i=mapVL.size();i<m;i++){//比较节点内的数据 TreeNode node=new TreeNode(0,(byte)0);//其余节点赋值为0 node.setLeft(nodes[0]); node.setRight(nodes[1]); nodes[0].setParent(node); nodes[1].setParent(node); node.times=nodes[0].times+nodes[1].times;//将次数存入节点 outArray(nodes);//移出头两个元素 insertOrder(nodes,node);//插入新节点 } return nodes[0];//最后一个点为根节点,值最大 } // 遍历树,左边标1,右边标0 private String strcode=""; public void codeTree(TreeNode root){//由下往上打印 byte keyB = root.keyB;//字节 if(root.getLeft()==null&&root.getRight()==null){//为叶子的时候,存入编码 //找到mapV中对应的keyB,加上HF编码 int pos=findPos(MapTest.mapV,keyB); //System.out.println("pos="+pos); if(pos!=-1){ MapTest.mapV.get(pos).code=strcode; //0,1编码存入队列 }else{ System.out.println("HF编码出错"); } } TreeNode left = root.getLeft(); if(left!=null){ //标1 strcode=strcode+"1"; codeTree(left); } TreeNode right = root.getRight(); if(right!=null){//只改变右子树,y的间距是不变的 //标0 strcode=strcode+"0"; codeTree(right); } //此时左右子树都为空,往上回一层 if(strcode.length()>0){ strcode=strcode.substring(0,strcode.length()-1);//不包括原来的第length()-1个 } } //找到mapVL中对应的keyB,并返回位置 public int findPos(java.util.ArrayList<MapValue> mapVL,byte key){ int pos=-1; for(int i=0;i<mapVL.size();i++){//只能根据字节找,因为出现次数不唯一 if(mapVL.get(i).keyB==key){ pos=i; break; } } return pos; } //冒泡排序,升序,大的往后; 最好适用于所有类型或数据结构 public void bubbleOrder(java.util.ArrayList<MapValue> mapVL){ for(int i=0;i<mapVL.size()-1;i++){//n-1次比较 for(int j=0;j<(mapVL.size()-1)-i;j++){ if(mapVL.get(j).times>mapVL.get(j+1).times){//交换顺序 MapValue tmp=new MapValue(); //交换整个对象 tmp=mapVL.get(j); mapVL.set(j, mapVL.get(j+1));//j变为j+1的对象 mapVL.set(j+1, tmp);//j+1变为原来j的对象 } } } //printArrayList(mapVL); } //插入排序 public void insertOrder(TreeNode a[],TreeNode node){ int i=0; while( node.times>a[i].times && i<n){ //大于再往后插入 i++; } n++; for(int j=n-1;j>i;j--){//往后移,node放在i位置 a[j]=a[j-1]; } a[i]=node; } //出数组,一次出两个 public void outArray(TreeNode a[]){ for(int i=2;i<n;i++){ a[i-2]=a[i]; } n=n-2;//记录比较大小数组的长度,每次少2个 //数组内后最后两个数字仍存在 } //输出队列mapVL public void printArrayList(java.util.ArrayList<MapValue> mapVL){ for(int i=0;i<mapVL.size();i++){ System.out.println("字节为"+mapVL.get(i).keyB); System.out.println("出现次数为"+mapVL.get(i).times); System.out.println("编码为"+mapVL.get(i).code); } } }
package treeV2; /** * 树的节点类 *包含了MapValue中的字节和次数属性 * @author Administrator * */ public class TreeNode { int times;// 节点中的数据对象 byte keyB;// 存读取文件的字节,若为字符会超出 private TreeNode parent;// 父节点 private TreeNode left;// 左子节点 private TreeNode right;// 右子节点 //构造函数,初始化节点数据,不要漏了数据 public TreeNode(int times,byte keyB){ this.times = times; this.keyB=keyB; } public byte getKeyB() { return keyB; } public void setKeyB(byte keyB) { this.keyB = keyB; } public int getObj() { return times; } public void setObj(int obj) { this.times = obj; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } public TreeNode getLeft() { return left; } public void setLeft(TreeNode left) { this.left = left; } public TreeNode getRight() { return right; } public void setRight(TreeNode right) { this.right = right; } }
package treeV2; //统计字节数组中每个字节出现的次数,并放在一个Map映射中 public class MapTest { static java.util.ArrayList<MapValue> mapV = new java.util.ArrayList<MapValue>(); /** * 根据传入的字节数组,统计每个字节出现的次数 * @param byt:字节数组 */ public java.util.Map<Byte, Integer> createMap(byte[] byt) { // 创建一个Map对象 java.util.Map<Byte, Integer> map = new java.util.HashMap<Byte, Integer>(); for(int i=0;i<byt.length;i++){ if(map.get(byt[i]) != null){ int sum=map.get(byt[i])+1; map.put(byt[i],sum ); //装入数据 }else {//数据在map中没有 map.put(byt[i],1); } } return map; } //取出map中数据,打印map,并存入java.util.ArrayList<MapValue> mapV public void mapToArraylist(java.util.Map<Byte, Integer> map){ //得到Map的Set集合 java.util.Set<Byte> keys = map.keySet();//返回此映射中包含的键的 Set 视图 //遍历Set //得到Set的迭代器 java.util.Iterator<Byte> iter = keys.iterator(); int i=0; while(iter.hasNext()){//是否有下一个,如果仍有元素可以迭代,则返回 true。 MapValue mapv=new MapValue(); //如果有就取一个 mapv.keyB = iter.next();//返回迭代的下一个元素。 //根据键取得对应的Value mapv.times= map.get(mapv.keyB); mapV.add(mapv);//加入队列 i++; } } //输出队列mapVL public void printArrayList(java.util.ArrayList<MapValue> mapVL){ for(int i=0;i<mapVL.size();i++){ System.out.println("字节为"+mapVL.get(i).keyB); System.out.println("出现次数为"+mapVL.get(i).times); System.out.println("编码为"+mapVL.get(i).code); } } }
相关推荐
《Java程序员面试宝典》主要内容简介:目前许多开发者对Java语言及其底层原理掌握不牢固,在面试过程中经常漏洞百出,无法取得好成绩。而招聘单位为了得到高素质的员工往往使出浑身解数,采用各种形式的面试考察求职...
(2)做出来的系统一定要能满足实际的需求,不能做一个华而不实的系统,也不能做一个漏洞百出的系统。 (3)在进行 java 开发时要和企业的开发保持一致,好是类似实战形式的 java 开发行为,不能说拿大学时候那种...
使用该软件你将告别了IS的繁冗,告别了霸道且漏洞百出的WINNT,WIN2000...等等限制,您将在一个任意版本下的视窗系统下调试或发布您的 ASP程序了。支持win9x/winme/win2k/Server/xp/2003。虽然这个软件的个头只有几...
目前许多开发者对Java语言及其底层原理掌握不牢固,在面试过程中经常漏洞百出,无法取得好成绩。而招聘单位为了得到高素质的员工往往使出浑身解数,采用各种形式的面试考察求职者,这让面试难度大大增加。求职者要想...
java最难笔试题Prolog 目标中的 Common Lisp The resulting Translation of CommonLisp into Prolog who's non-special forms become special FEXPRs (operands are always passed unevaluated!) give us the ...
存档,记录不良,漏洞百出且未经测试,但有趣且经过优化的“ Java中的现代射线广播引擎” 我放弃了这个项目,但如果您对此项目感兴趣,请打开一个pullrequest。 这是一个“真正的”光线投射引擎。 这应该意味着...
小旋风ASPWEB服务器2005 可代替IIS调试ASP程序软件介绍 套强大简洁的ASPWEB服务器,使用这个软件的您完全可以抛弃体积庞大的WINNT,WIN2000服 务器系统及漏洞百出的IIS了。现在你可以在任何一个系统上调试和发布您...
本人的下载积分快没了 所以设置5个资源分 大家不要骂我 ">鉴于目前网上流行的资料关于PhoneGap Cordova 的配置教程几乎都是1 3版本 另外又由于官网的文档漏洞百出 一直报:java lang RuntimeException:Unable to ...
现在你可以在任何一个系统上调试和发布您的ASP程序了。目 前测试通过的操作系统为:Windows 98;Windows 98 SE;Windows ME;Windows NT+IE4; Windows 2000;Windows XP;Windows .NET Server。现在完全支持...
现在你可以在任何一个系统上调试和发布您的ASP程序了。目 前测试通过的操作系统为:Windows 98;Windows 98 SE;Windows ME;Windows NT+IE4; Windows 2000;Windows XP;Windows .NET Server。现在完全支持...
黑风ASP服务器使用该软件你将告别了IS的繁冗,告别了霸道且漏洞百出的WINNT,WIN2000...等等限制,您将在一个任意版本下的视窗系统下调试或发布您的ASP程序了。支持win9x/winme/win2k/Server/xp/2003。虽然这个软件的...
WebGoat是由著名的OWASP负责维护的一个漏洞百出的J2EE Web应用程序,这些漏洞并非程序中的bug,而是故意设计用来讲授Web应用程序安全课程的。这个应用程序提供了一个逼真的教学环境
WebGoat是由著名的OWASP负责维护的一个漏洞百出的J2EE Web应用程序,这些漏洞并非程序中的bug,而是故意设计用来讲授Web应用程序安全课程的。这个应用程序提供了一个逼真的教学环境,
该软件是由lamp开发的一套强大的ASPWEB服务器,使用这个软件的您完全可以抛弃体积庞大的WINNT,WIN2000服 务器系统及漏洞百出的IIS了。现在你可以在任何一个系统上调试和发布您的ASP程序了。目前测试通过的操作系统...
现在你可以在任何一个系统上调试和发布您的ASP程序了。目 前测试通过的操作系统为:Windows 98;Windows 98 SE;Windows ME;Windows NT+IE4; Windows 2000;Windows XP;Windows .NET Server。现在完全支持...
4、 SSL客户端可以采用SSL协议连接一些提供SSL服务的网站,程序里列举了一些。 5、 SSL服务器可以作为一个独立的服务器提供SSL服务,注意不能在同一个程序中用SSL客户端连接SSL服务器,用SSL客户端连接服务器出现半...
4. **设计模式**:单例模式、工厂模式、观察者模式、装饰器模式等23种设计模式的理解与应用,理解它们在软件设计中的作用和实现方式。 5. **计算机网络**:TCP/IP协议栈、HTTP/HTTPS协议、三次握手四次挥手、Socket...
该软件是由残剑无敌在NETBOX核心下开发的一套强大简洁的ASPWEB服务器,使用这个软件的您完全可以抛弃体积庞大的WINNT,WIN2000服务器系统及漏洞百出的IIS了。现在你可以在任何一个系统上调试和发布您的ASP程序了。...