亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

哈夫曼壓縮

系統 2025 0

?? 這幾天完成了哈夫曼原理壓縮文件的實現.. 雖然這個實現壓縮的速度相當讓人蛋疼.. 不過這也算是加深了對壓縮原理的的理解吧.? 話說. 我還用系統給的類寫了個Zip格式的壓縮.. 比較之下才發現自己寫的那些代碼實在是不及他人的皮毛啊. 同樣是一個類. 我的效率比起系統的來說......? 這根本就是沒法比啊.? 前路漫漫. 自己要學的,要改的還有很多啊..? 先談談自己的這個上不了眼壓縮.. 首先是統計各個字節出現的次序

?

    // 創建映射集,每個字節對應其出現的次數.
		HashMap<Byte, Integer> map = new HashMap<Byte, Integer>();
		try {// 文件地址正確的時候創建文件輸入流
			FileInputStream fis = new FileInputStream(path);
			// 封裝成緩沖流
			BufferedInputStream bis = new BufferedInputStream(fis);

			int len = bis.available();
			// 每次讀取一個字節
			byte data;
			file = new byte[len];
			int i = 0;
			while (len > 0) {
				data = (byte) bis.read();
				// System.out.println(data);
				file[i] = data;
				// 如果字節在映射中不存在,則放入1
				if (map.get(data) == null) {
					map.put(data, 1);
				} else {// 如果字節在映射中已經存在,則value值在原來基礎上加1
					map.put(data, map.get(data) + 1);
				}
				i++;
				len = bis.available();
			}
			fis.close();

		} catch (Exception ef) {
			ef.printStackTrace();
		}
  

?然后再根據各字節出現過的次數大小(即各個字節出現的頻率)來構造哈夫曼樹,并通過這棵哈夫曼樹來為每個字節編碼,于是每個字節都有一個唯一的哈夫曼編碼與之對應.然后再通過文件中各個字節的順序來得到整個文件的所有字節的哈夫曼編碼,再將這些編碼分割成8位8位的.. 然后就能將這些字符串變成字符串寫到文件中去了.

?

    // 創建文件輸出流
			FileOutputStream fos = new FileOutputStream(des);

			// 包裝成基本類型數據流將字節長度寫入文件
			DataOutputStream dos = new DataOutputStream(fos);
			// String轉化成的字節數組的長度
			dos.writeInt(str.length() / 8 + 1);

			byte[] by;
			// 字符串的長度
			int slen = str.length();
			if (slen % 8 == 0) {// 如果字符串長度正好是8的整數倍,即說明最后沒有補0,byte數組的最后一個數放0,表示沒有補0
				dos.writeInt(1);// 字符串大小正好是8的整數倍
				by = new byte[slen / 8 + 1];
				String s;
				int c = 0;
				// 循環,每次得到一個8位的01串
				while (str.length() >= 8) {
					// 得到8位01串
					s = str.substring(0, 8);
					BigInteger bi = new BigInteger(s, 2);// 將01串轉換為BigInteger類型
					String s1 = bi.toString(10);// 轉換為10進制結果
					int i = Integer.valueOf(s1);
					by[c] = (byte) i;
					strlist1.put(by[c], s);

					// 將得到的8位01串丟掉.
					str = str.substring(8);
					c++;
				}
				by[c] = 0;
				dos.write(by);
			} else {// 如果字符串長度不是8的整數倍,則說明要多留出一位來存放那個不滿8zz位的"字節",同時還要多一位來存放補上的0的個數.
				dos.writeInt(0);// 字符串的長度不是8的整數倍
				by = new byte[slen / 8 + 2];
				String s;
				int c = 0;
				// 循環,每次得到一個8位的01串
				while (str.length() > 8) {
					// 得到8位01串
					s = str.substring(0, 8);
					BigInteger bi = new BigInteger(s, 2);// 將01串轉換為BigInteger類型
					String s1 = bi.toString(10);// 轉換為10進制結果
					int i = Integer.valueOf(s1);
					by[c] = (byte) i;
					strlist1.put(by[c], s);
					// 將得到的8位01串丟掉.
					str = str.substring(8);
					c++;
				}
				// 往字符串后面補0.
				int sl = str.length();
				for (int k = 0; k < 8 - sl; k++) {
					str += 0;
				}
				BigInteger bi = new BigInteger(str, 2);// 將01串轉換為BigInteger類型
				String str1 = bi.toString(10);// 轉換為10進制結果
				int i = Integer.valueOf(str1); // 將字符串轉成int類型
				by[c] = (byte) i; // 強制轉型成byte類型.放入數組,寫到文件中.
				strlist1.put(by[c], str);
				by[c + 1] = (byte) (8 - sl);
				dos.write(by);
			}
			// 包裝成對象輸入流將碼表直接以對象的形式寫入文件
			ObjectOutputStream oos;
			oos = new ObjectOutputStream(fos);
			oos.writeObject(writemap);
			oos.writeObject(strlist1);

			oos.flush();

			// 強制輸出
			dos.flush();
			fos.close();
  

?由于上次在實現自定義畫板的文件保存時,用了對象數據流, 嘗到了甜頭.. 于是我這次的碼表就直接用對流輸出流來寫.. 這個方法雖然省事.. 但是會產生"副作用":會降低壓縮比率.. 貌似對讀寫的時間也有影響..

?

?

接下來就是解壓了.. 其實就是壓縮的逆過程吧,, 只要好好注意.. 自己是怎么樣把各個字節寫入的,再一步一步將其還原回來就是了.

?

    // 得到文件地址
			FileInputStream fis = new FileInputStream(src);
			FileOutputStream fos = new FileOutputStream(des);

			// 包裝成數據流
			DataInputStream dis = new DataInputStream(fis);
			DataOutputStream dos = new DataOutputStream(fos);

			int arraylen;
			// 讀取字節數組的長度
			arraylen = dis.readInt();
			int flag = dis.readInt();// 此處a為標志,1表示被壓縮的源文件的哈夫曼編碼總長度是8的整數倍
			// 0表示被壓縮的源文件的哈夫曼編碼的總長度不是8的整數倍

			// 被壓縮文件的源文件的哈夫曼編碼長度是8的整數倍,即只多了一位放0.(arraylen==slen%8+1)
			if (flag == 1) {
				by = new byte[arraylen - 1];// 最后一位直接丟棄
				dis.read(by);
				dis.read();
				ObjectInputStream ois = new ObjectInputStream(fis);
				maps = (HashMap) ois.readObject();
				m = (HashMap) ois.readObject();
				// 將字節數組轉成字符串
				String s1 = "";
				for (int k = 0; k < by.length; k++) {
					s1 += m.get(by[k]);
				}
				String s2;
				int s2l = 0;
				int sl = 1;
				int s1l = s1.length();
				while (s1l > 0) {
					// 首先從一位開始找匹配,找到就寫文件
					s2 = s1.substring(s2l, sl);
					while (maps.get(s2) == null) {
						sl++;
						s2 = s1.substring(s2l, sl);
					}
					dos.write(maps.get(s2));
					s1 = s1.substring(sl);
					s2l = 0;
					sl = 1;
					s1l = s1.length();
				}
			} else {// 不是8的整數倍..(arraylen==slen%8+1)
				by = new byte[arraylen];
				dis.read(by);
				byte num = dis.readByte();// 讀出最后一個記錄補0個數的字節
				ObjectInputStream ois = new ObjectInputStream(fis);
				maps = (HashMap) ois.readObject();
				m = (HashMap) ois.readObject();
				String s = "";
				for (int k = 0; k < by.length; k++) {
					s += m.get(by[k]);
				}
				int initlen = s.length();
				s = s.substring(0, initlen - (int) num);// 截取第一位到補0的第一位.
				String s2;
				int s2l = 0;
				int sl = 1;
				int s1l = s.length();
				while (s1l > 0) {
					// 首先從一位開始找匹配,找到就寫文件
					s2 = s.substring(s2l, sl);
					while (maps.get(s2) == null) {
						sl++;
						s2 = s.substring(s2l, sl);
					}
					dos.write(maps.get(s2));
					s = s.substring(sl);
					s2l = 0;
					sl = 1;
					s1l = s.length();
				}

			}
			dos.flush();
			fos.close();
  

?

鑒于壓縮一個大文件實在是太慢了.. 就選了一個比較小的文件來示例了.. 壓縮的比率也的確不高啊....



?

?

?

?

然后就是利用系統提供的一個類.寫了個壓縮成zip格式的文件.? 壓縮完了之后直能用zip格式解壓器就能打開.像winRAR就能直接打開查看..? 用了這個類... 代碼量少了不止是一行兩行,, 壓縮的速度.. 壓縮的比率... 唉 , 看得人糾結啊.. 學無止境呀,還有很多東西需要好好努力去學..


不過這個方法暫時還有點小問題沒解決..? 中文名字亂碼!!? 這是java使用的是unicode編碼.. 而winRAR卻不是.. 所以才導致了這個問題.. 這個問題還真讓我有點蛋疼,, 實在不行的話就自己寫個類來解壓吧..呵呵..

具體實現暫時還只寫了個壓縮的方法. 并且只給了固定的地址的壓縮.

哈夫曼壓縮


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 2021久久精品永久免费 | 日日夜夜天天人人 | 亚洲精品中文字幕不卡在线 | 一区二区三区高清在线 | 色综合久久综合网 | 日本一本在线观看 | 视频一区二区国产无限在线观看 | 高清性色生活片久久久 | 奇米影视4444 | 欧美日韩一区二区三在线 | 久久久精品2021免费观看 | 高清一级毛片一本到免费观看 | 日本三级做a全过程在线观看 | 在线观看国产福利 | 亚洲欧美综合一区 | 69热在线观看 | 高清一区高清二区视频 | 日本免费不卡视频一区二区三区 | 亚洲视频精品在线观看 | 免费精品久久久久久中文字幕 | 欧美精品四虎在线观看 | 99视频都是精品热在线播放 | 久青草视频免费观看青 | 91精品国产免费自在线观看 | 国产午夜精品不卡观看 | 九九热精品视频在线 | 久久午夜网 | 国产伦精品一区二区三区免费迷 | 国产精品国产三级国产 | 亚洲精品乱码久久久久久v 亚洲精品乱码久久久久久麻豆 | 国产亚洲精品国产一区 | 久久爱成人网 | 九九久久精品国产 | 中文字幕一区二区区免 | 老司机精品在线播放 | 深夜成人性视频免费看 | 九九九精品午夜在线观看 | 久久影院朴妮唛 | 一级毛片成人免费看a | 欧美毛片 | 亚洲欧美自拍一区 |