使用Java實現網絡傳輸數據的壓縮
[ 作者:liudong    轉貼自:Matrix    點擊數:150    更新時間:2005-6-1    文章錄入:sailing
本周,我回答了兩個使用Java進行數據壓縮的問題.

第一個問題是: 我怎樣才能壓縮那些不在文件中的數據.

第二個問題是: 我以極大的熱情閱讀了Todd Sundsted的"壓縮你的數據,從而提高你的網絡應用程序的性能",但是讀完后我卻有點失望.當我讀到文章標題時我很高興.我想我總算找到了解決問題的辦法了.

在我們的公司,我們試圖提高一個組織數據的RMI應用程序的性能.服務器端進行了絕大部分的處理和優化.我們花了一年半的時間去提高性能,但是現在看來瓶頸在于數據的傳輸上.在一天的任何時間內,我們都有可能在客戶和服務器之間傳送成千上萬的數據.

一種可能的解決辦法,我建議我們能夠在把數據返回給客戶端時先壓縮這些數據,這在Todd的文章中已經說得很清楚了.但是,文章中的例子卻是壓縮文件,而不是我們所需要的----對數據進行壓縮.

在RMI中的實現中,我們先從數據庫取得數據,再把數據放入一個列表中,接著把這個列表返回給客戶端,最后再把它們插入JTable中.我想在把數據返回給客戶時,首先把列表中的數據壓縮,然后在客戶端解壓縮,最后把數據插入到表格中.

這樣的想法可行嗎?

A:最近我收到了一些關于Todd的文章的疑問.很多讀者看起來對文章中的舉例很疑惑.因為文章中的例子是以文件壓縮為核心的.

首先回答第一個問題,當你使用ZipInputStream 和 ZipOutputStream 并沒有強制你必須使用文件.唯一要注意的是你必須把數據轉換為字節數組的形式.

第二個問題比較棘手.在網絡中,以RMI方式通信就需要作一些調整了.為了在傳送數據之前就讓RMI進行數據壓縮,你必須創建一個能夠壓縮數據的新的套接字.然后,當你創建了一個套接字后,你得告訴RMI使用這一套接字.

以下是創建一個RMI形式的套接字的簡要步驟:

1:選擇或者創建一個新的套接字.(可以參看SUN'S的"創建一個典型的套接字").

2:創建一個服務器端的套接字.

3:創建一個RMIClientSocketFactory

4:創建一個RMIServerSocketFactory

5:創建一個繼承了UnicastRemoteObjec的遠程對象,從而使用新的factories.

根據這一大致的想法,我們來看每一步如何具體的實現.

步驟1: 創建ZipSocket 

由于要進行Zip壓縮,我們重新創建這樣的套接字

mport java.io.InputStream;

import java.io.OutputStream;

import java.util.zip.ZipInputStream;

import java.util.zip.ZipOutputStream;

import java.net.Socket;

public class ZipSocket extends Socket {



private InputStream in;

private OutputStream out;



public ZipSocket() { super(); }



public ZipSocket(String host, int port) 

throws IOException {

super(host, port);

}



public InputStream getInputStream() 

throws IOException {

if (in == null) {

in = new ZipInputStream(super.getInputStream());

}

return in;

}



public OutputStream getOutputStream() 

throws IOException {

if (out == null) {

out = new ZipOutputStream(super.getOutputStream());

}

return out;

}



public synchronized void close() throws IOException {

OutputStream o = getOutputStream();

o.flush();

super.close();

}

}





步驟2: 創建ZipServerSocket 



import java.net.ServerSocket;

import java.net.Socket;

import java.io.IOException;



public class ZipServerSocket extends ServerSocket

{

public ZipServerSocket(int port) throws IOException { 

super(port);

}



public Socket accept() throws IOException { 

Socket socket = new ZipSocket();

implAccept(socket);

return socket;

}

}





步驟3:創建ZipClientSocketFactory 

客戶端的factory的創建必須遵循以下的形式: 



import java.io.IOException; 

import java.io.Serializable; 

import java.net.Socket; 

import java.rmi.server.RMIClientSocketFactory;



public class ZipClientSocketFactory 

implements RMIClientSocketFactory, Serializable { 

public Socket createSocket(String host, int port) 

throws IOException { 

ZipSocket socket = new ZipSocket(host, port); 

return socket; 



}



步驟4:創建ZipServerSocketFactory 



import java.io.IOException; 

import java.io.Serializable; 

import java.net.ServerSocket; 

import java.rmi.server.RMIServerSocketFactory; 



public class ZipServerSocketFactory 

implements RMIServerSocketFactory, Serializable { 



public ServerSocket createServerSocket(int port) 

throws IOException { 

ZipServerSocket server = new ZipServerSocket(port); 

return server; 



}



步驟5: 創建一個繼承了UnicastRemoteObjec的遠程對象,從而使用新的factories. 

public class YourRMIObject extends UnicastRemoteObject {



public YourRemoteObject( int port ) {

super( port, new ZipClientSocketFactory(), new ZipServerSocketFactory() );

}



// 剩下的是你自己的程序實現



}



現在你的通信數據得到了壓縮.





關于作者:

Tony Sintes 是一個獨立咨詢人,同時也是First Class Consulting, Inc. 的創始人.這一咨詢公司主要致力與對各個不同的企業系統進行量身定制和培訓 . 業余時間,Tony 是一個積極的自由作家,同時也是Sams出版的<<21天學通面向對象編程>>的作者 (Sams, 2001; ISBN: 0672321092).