數據字段一般都是保存原文的,一來方便在數據庫修改和維護,而來有一些查詢要用到它。但是在有些時候,我們無需保存原文了,比如在論壇,博客等數據裡的內容字段,一般使用Clob類型,其很少參與搜索,而且就算要全文檢索,我們也不推薦使用數據庫的like 等,而應該用第三方的全文檢索工具,比如lucene等實現。
這類數據都是大量的文本數據,有很大的可壓縮性。由於一些原因,我的數據庫已經超過我能容忍的大小了,所以想到了是否可以把這個數據壓縮存儲來節省空間,於是有了如下的嘗試。
壓縮算法就先不過多考慮了,就用Zip進行嘗試就可以了。先看看如何把字符串壓縮和解壓縮的算法。
package com.laozizhu.article.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* 把字符串使用ZIP壓縮和解壓縮的代碼。
*
* @author JAVA世紀網(java2000.net, laozizhu.com)
*/
public class StringZip {
public static String zipString(String str) {
try {
ByteArrayOutputStream bos = null;
GZIPOutputStream os = null;
byte[] bs = null;
try {
bos = new ByteArrayOutputStream();
os = new GZIPOutputStream(bos);
os.write(str.getBytes());
os.close();
bos.close();
bs = bos.toByteArray();
return new String(bs, "iso-8859-1");
} finally {
bs = null;
bos = null;
os = null;
}
} catch (Exception ex) {
return str;
}
}
public static String unzipString(String str) {
ByteArrayInputStream bis = null;
ByteArrayOutputStream bos = null;
GZIPInputStream is = null;
byte[] buf = null;
try {
bis = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
bos = new ByteArrayOutputStream();
is = new GZIPInputStream(bis);
buf = new byte[1024];
int len;
while ((len = is.read(buf)) != -1) {
bos.write(buf, 0, len);
}
is.close();
bis.close();
bos.close();
return new String(bos.toByteArray());
} catch (Exception ex) {
return str;
} finally {
bis = null;
bos = null;
is = null;
buf = null;
}
}
}
然後就是如何壓縮和解壓縮,應該放在哪裡的問題。我考慮了一下,發現JavaBean這東西真的有趣,竟然可以實現透明壓縮和解壓縮。看代碼:
private String content;
// 增加一個是否壓縮的字段,沒辦法,有些字段壓縮了反到更長了
private boolean ziped;
public boolean isZiped() {
return ziped;
}
public void setZiped(boolean ziped) {
this.ziped = ziped;
}
**
* 讀取內容。
* @return the content
*/
public String getContent() {
// 解碼
if (isZiped()) {
return StringZip.unzipString(content);
}
return content;
}
/**
* 設置新的內容
* @param content the content to set
*/
public void setContent(String content) {
if (content == null || content.length() < 512) {
this.content = content;
ziped = false;
} else {
// 嘗試編碼
this.content = StringZip.zipString(content);
// 如果編碼後的數據更長
if (this.content.length() > content.length()) {
this.content = content;
ziped = false;
} else {
ziped = true;
}
}
}
增加了一個是否壓縮的屬性。
在讀取時,根據是否壓縮的標志進行操作,在設置時,根據數據長度和壓縮的效果更新數據,並設置壓縮標志。
通過這個,數據將被壓縮保存,一般的文本壓縮率還是很高的,到底有多高,你自己測試看看就知道了。