字符串壓縮:
之前在做Android客戶端開發的時候,需要請求一個字典類型的http請求接口,由於接口json數據過大,達到6M,當時建議後端對接口返回的json數據邏輯進行處理,在服務端將json串壓縮,然後在客戶端進行解壓,最後在將數據顯示在客戶端。
Java實現字符串壓縮API:
壓縮算法有多種,我說知道和接觸有java I/O自帶的zip和gzip兩種方式,此次的壓縮和解壓用到的主要就是GZIPOutputStream和GZIPInputStream類,看一下例子:
字符串壓縮代碼:
public static String compress(String source) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
GZIPOutputStream gos = new GZIPOutputStream(bos);
gos.write(source.getBytes("ISO-8859-1"));
gos.close();
return bos.toString("ISO-8859-1");
} catch (IOException var3) {
System.out.println(var3.getStackTrace().toString());
return source;
}
}
字符串解壓代碼:
/****
* @Method compress 字符串解壓方法
* @author source 需要傳入待解壓的字符串
* 返回值 返回解壓後的字符串
****/
public static String uncompress(String source) {
if (source != null && source.length() != 0) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(source.getBytes("ISO-8859-1"));
GZIPInputStream gis = new GZIPInputStream(bis);
byte[] data = new byte[1024];
for(int len = gis.read(data); len != -1; len = gis.read(data)) {
bos.write(data, 0, len);
}
return bos.toString();
} catch (IOException var6) {
System.out.println(var6.getStackTrace().toString());
return source;
}
} else {
return source;
}
}
測試代碼:
public static void main(String[] args) {
// 字符串超過一定的長度
String str = "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggfdgfdgf"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggABCdef123中文~!@#$%^&*()_+{fd}"
+ ";/1111111111111111111111111AAAAAAAAAAAJDLFJDLFJDLFJLDFFFFJEIIIIIIIIIIFJJJJJJJJJJJJALLLLLLLLLLLLLLLLLLLLLLdddddddddddddddddfdfdfdfdfdfdd"
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddessdfrdfdfd"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddgfgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggf"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddddddddddddddddddddddddddddddddddddddddggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg" +
"LLppppppppppppppppppppppppppppppppppppppppp===========================------------------------------iiiiiiiiiiiiiiiiiiiiiiiggggggggggggg";
//字符串原始長度處理
String originalStr = str;
System.out.println("原始的字符串長度:" + originalStr.length());
//字符串壓縮狀態處理
String compressStr = compress(originalStr);
System.out.println("壓縮的字符串長度:" + compressStr.length());
//字符串解壓方法以及測試解壓後字符串長度
String uncompress = uncompress(compressStr);
System.out.println("解壓後的字符串長度:" + uncompress.length());
//字符串壓縮率
float rate = (float)compressStr.length() / uncompress.length();
System.out.println("字符串壓縮率:" + rate);
if(originalStr.equals(uncompress)){
System.out.println("解壓後的字符串和原始的字符串長度一樣");
}
}
控制檯打印輸出結果:
原始的字符串長度:1474
壓縮的字符串長度:136
解壓後的字符串長度:1474
字符串壓縮率:0.09226594
如圖通過調研compress壓縮方法將原始字符串壓縮,原始字符串的長度爲1474個字節,壓縮後字符串大小變爲136個字節,字符串的壓縮率達到91%。
Java代碼實現文件壓縮與解壓:
api說明:
1:添加ZipTools包(主要解決中文路徑壓縮解壓亂碼問題)
2:文件壓縮需要用到的類 ZipOutputStream(zip文件壓縮需要用到的類)
3:ZipEntry 壓縮文件的子文件對象,用於保存壓縮文件中文件及其文件夾的一個實列
4:ZipFile 壓縮文件的實列,用於zip的解壓操作
文件壓縮相關代碼:
/****
*
* @Method createZipStream 創建ZIP輸出流實例
* @param filePath 需要壓縮的文件以及路徑
* @param fileOutPath 生成壓縮的文件以及路徑
*
****/
public static void createZipStream(String filePath, String fileOutPath) throws IOException{
OutputStream os = new FileOutputStream(fileOutPath);//根據壓縮的文件路徑創建要輸出的文件
CheckedOutputStream cos = new CheckedOutputStream(os, new CRC32());//檢查輸出流,採用crc算法,保證文件的一致性
ZipOutputStream zos = new ZipOutputStream(cos);//定義zip文件輸出流
zos.setEncoding("GBK");//設置編碼格式,防止中文亂碼
File file = new File(filePath);//需要壓縮的文件以及文件夾對象
compressFile(zos,file);
zos.close();
cos.close();
os.close();
System.out.println("壓縮文件完成");
}
/****
* @Method compressFile
* @param ZipOutputStream zip文件輸出流
* @param File 要壓縮的文件對象
****/
public static void compressFile(ZipOutputStream zos, File file) throws IOException{
String fp = file.getPath().substring(3,file.getPath().length());//去掉盤符
if(file.isDirectory()){//如果是文件目錄,添加當前文件夾到zip文件流中
zos.putNextEntry(new ZipEntry(fp + File.separator));
for(File f: file.listFiles()){
compressFile(zos, f);
}
}else{//如果是文件目錄,添加當前文件到zip文件流中
System.out.println("正在壓縮文件:"+file.getPath());
zos.putNextEntry(new ZipEntry(fp));
InputStream is = new FileInputStream(file.getPath());//用字節方式讀取文件
BufferedInputStream bis = new BufferedInputStream(is);//創建一個緩存區
byte [] b = new byte[1024];
//將讀取的字節寫到zip文件流中
while (bis.read(b) != -1) {
zos.write(b);
}
bis.close();
is.close();
}
}
測試函數以及返回示例:
public static void main(String[] args) throws IOException {
createZipStream(filePath,fileOutPath);
// unCompressFile(fileOutPath);
}
打印壓縮文件過程:
正在壓縮文件:D:\MyDrivers\backup\dgsetup.exe
正在壓縮文件:D:\MyDrivers\backup\driverlist.mf
正在壓縮文件:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\rt640x64.inf
正在壓縮文件:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\rt640x64.PNF
正在壓縮文件:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\rt640x64.sys
壓縮文件完成
文件解壓相關函數:
/***
*
* @Method unCompressFile
* @param filePath 需要解壓的文件路徑
*
***/
public static void unCompressFile(String filePath) throws IOException{
File file = new File(filePath);
if(!file.exists()){
System.out.println("當前壓縮文件不存在");
return;
}
ZipFile zipFile = new ZipFile(file.getPath(),"GBK");
for(Enumeration<ZipEntry> enumeration = zipFile.getEntries();enumeration.hasMoreElements();){//循環獲取zip文件壓縮實例
ZipEntry zipEntry = enumeration.nextElement();//獲取元素
//如果是空文件不解壓
if(!zipEntry.getName().equals(File.separator)){
String path = "D:\\" + zipEntry.getName();
System.out.println("文件名:" + path);
int len = path.length();
//創建解壓目錄
if(path.substring(len - 1, len).equals("\\")){
File createFile = new File(path);
if(!createFile.exists()){
createFile.mkdirs();//如果當前文件不存在,則創建解壓目錄
}
}else{
//創建解壓後的文件
OutputStream os = new FileOutputStream(new File(path));
BufferedOutputStream bos = new BufferedOutputStream(os);//帶緩衝的寫出流
InputStream is = zipFile.getInputStream(zipEntry);//讀取元素
BufferedInputStream bis = new BufferedInputStream(is);
CheckedInputStream cis = new CheckedInputStream(bis, new CRC32());//檢查讀取流,用CRC算法檢查文件是否一致性
byte[] b = new byte[1024];//字節數組,每次讀取1024個字節
//循環讀取解壓文件的值,將zip流寫入新文件中
while (cis.read(b) != -1) {
bos.write(b);
}
cis.close();
bis.close();
is.close();
bos.close();
os.close();
}
}else{
System.out.println("目錄名:" + zipEntry.getName());
}
}
System.out.println("文件解壓結束");
}
測試解壓方法:
public static void main(String[] args) throws IOException {
// createZipStream(filePath,fileOutPath);
unCompressFile(fileOutPath);
}
打印解壓文件結果:
文件名:D:\MyDrivers\backup\
文件名:D:\MyDrivers\update\
文件名:D:\MyDrivers\backup\dgsetup.exe
文件名:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\
文件名:D:\MyDrivers\software\disapp\
文件名:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\rt640x64.inf
文件名:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\
文件名:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\rt640x64.PNF
文件名:D:\MyDrivers\backup\driverlist.mf
文件名:D:\MyDrivers\
文件名:D:\MyDrivers\backup\Realtek PCIe GBE Family Controller\rt640x64.inf_amd64_98de0ddb0966f29b\rt640x64.sys
文件名:D:\MyDrivers\hotfix\
文件名:D:\MyDrivers\software\
文件解壓結束
自己封裝的字符串壓縮和文件壓縮庫:
項目目錄結構截圖如下:
java_zip.jar包是我封裝的字符串和文件壓縮jar,slf4j-api-1.7.21.jar,slf4j-nop-1.7.2.jar爲代碼依賴的日誌包,ziptools.jar爲JavaApi zip防止中文亂碼開發的包。
Api演示代碼如下:
public static String filePath = "D:/MyDrivers/";
public static String fileOutPath = "D:/MyDrivers.zip";
//在lib文件中有一個Java_zip.jar
public static void main(String[] args) {
// 字符串超過一定的長度
String str = "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggfdgfdgf"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggABCdef123中文~!@#$%^&*()_+{fd}"
+ ";/1111111111111111111111111AAAAAAAAAAAJDLFJDLFJDLFJLDFFFFJEIIIIIIIIIIFJJJJJJJJJJJJALLLLLLLLLLLLLLLLLLLLLLdddddddddddddddddfdfdfdfdfdfdd"
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddessdfrdfdfd"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddgfgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggf"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddddddddddddddddddddddddddddddddddddddddggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg" +
"LLppppppppppppppppppppppppppppppppppppppppp===========================------------------------------iiiiiiiiiiiiiiiiiiiiiiiggggggggggggg";
System.out.println("字符串初始長度:" + str.length());
String compressstr = GzipUtils.compress(str);
System.out.println("壓縮後字符串長度:" + compressstr.length());
String uncompress = GzipUtils.uncompress(compressstr);
System.out.println("解壓後字符串長度:" + uncompress.length());
//壓縮文件
// ZipUtil.pack(new File(filePath), new File(fileOutPath));
//解壓文件
ZipUtil.unpack(new File(fileOutPath), new File(filePath));