讀者范圍
:
本文是一篇簡短入門文章
.
本文假設讀者對
Java
的
IO
系統(tǒng)和
Java
的網絡系統(tǒng)有所了解
.
正文
:
關于文件傳輸?shù)膯栴}
,
實際也是一種
IO
讀寫的基本問題
.
對于網絡而言也是一種
IO
讀寫問題
.
因此所謂網絡的文件傳輸實際是兩種
IO
問題的綜合討論
.
這里我們首先分析一個圖示
.
然后圍繞這個圖示來討論
:
圖
1
:
分析圖
1
我們基本可以知道從服務器文件系統(tǒng)中通過流把文件中的數(shù)據(jù)寫入到服務器的進程中
,
然后把進程中的數(shù)據(jù)通過網絡
IO
系統(tǒng)傳遞到客戶機
,
這個階段
,
網絡中的數(shù)據(jù)以字節(jié)流的形式保存
.
當該字節(jié)流被客戶進程接受后
,
客戶進程通過客戶本地文件流寫入客戶本地的文件系統(tǒng)中
.
根據(jù)以上分析
,
我們基本可以確定我所需要處理的問題了
.
首先我們需要可以對本地文件系統(tǒng)
IO
操作的操作接口
,
然后是一個可以對網絡
IO
系統(tǒng)進行操作的操作接口
,
已經一個可以把數(shù)據(jù)包裝成字節(jié)流的操作接口
,
他們分別可以提供客戶和服務器兩個進程進行讀寫的操作
.
如下圖所示
:
圖
2:
根據(jù)以上分析
,
我們可以把問題歸結到對以下編程接口的需求上
:
1.
字節(jié)包裝器和字節(jié)解包器
,
2.
網絡傳輸器和網絡接收器
3.
本地文件讀
/
寫器
而這些
Java
本身的
API
就已經提供
.
他們都被包裝到
java.io
和
java.net
這兩個包里
,
這里我提供一個基于
TCP/IP
的實現(xiàn)版本
,
使用基于連接的方式來完成工作
.
我們首先介紹幾個相關的
JDK
中的類來完成以上任務
,
1.
DataOutputStream
和
DataInputStream
實現(xiàn)類提供了上面的字節(jié)包裝和解包器的實現(xiàn)
2.
ServerSocket
和
Socekt
提供了基于連接的網絡傳輸和接受接口
3.
File,FileInputStream
和
FileOutputStream
提供了基本的本地文件輸入輸出接口
.
服務器端實現(xiàn)代碼
:
import java.io.*;
import java.net.*;
public class FileServer{
public static void main(String[] args)throws Exception{
//
創(chuàng)建文件流用來讀取文件中的數(shù)據(jù)
File file=new File("lishengjie.jpg");
FileInputStream fos=new FileInputStream(file);
//
創(chuàng)建網絡服務器接受客戶請求
ServerSocket ss=new ServerSocket(3108);
Socket client=ss.accept();
//
創(chuàng)建網絡輸出流并提供數(shù)據(jù)包裝器
OutputStream netOut=client.getOutputStream();
OutputStream doc=new DataOutputStream(new BufferedOutputStream(netOut));
//
創(chuàng)建文件讀取緩沖區(qū)
byte[] buf=new byte[2048];
int num=fos.read(buf);
while(num!=(-1)){//
是否讀完文件
doc.write(buf,0,num);//
把文件數(shù)據(jù)寫出網絡緩沖區(qū)
doc.flush();//
刷新緩沖區(qū)把數(shù)據(jù)寫往客戶端
num=fos.read(buf);//
繼續(xù)從文件中讀取數(shù)據(jù)
}
fos.close();
doc.close();
}
}
客戶方實現(xiàn)代碼
:
import java.io.*;
import java.net.*;
public class FileClient{
public static void main(String[] args)throws Exception{
//
使用本地文件系統(tǒng)接受網絡數(shù)據(jù)并存為新文件
File file=new File("newFile.jpg");
file.createNewFile();
RandomAccessFile raf=new RandomAccessFile(file,"rw");
//
通過
Socket
連接文件服務器
Socket server=new Socket(InetAddress.getLocalHost(),3108);
//
創(chuàng)建網絡接受流接受服務器文件數(shù)據(jù)
InputStream netIn=server.getInputStream();
InputStream in=new DataInputStream(new BufferedInputStream(netIn));
//
創(chuàng)建緩沖區(qū)緩沖網絡數(shù)據(jù)
byte[] buf=new byte[2048];
int num=in.read(buf);
while(num!=(-1)){//
是否讀完所有數(shù)據(jù)
raf.write(buf,0,num);//
將數(shù)據(jù)寫往文件
raf.skipBytes(num);//
順序寫文件字節(jié)
num=in.read(buf);//
繼續(xù)從網絡中讀取文件
}
in.close();
raf.close();
}
}
歸結以上代碼
:
服務器
|
客戶端
|
1.
服務器從本地文件系統(tǒng)讀取文件
2.
服務器創(chuàng)建網絡服務連接
3.
服務器提供數(shù)據(jù)包裝器
4.
服務器將本地文件寫入數(shù)據(jù)包裝器
5.
服務器通過包裝器寫入到網絡
|
1.
客戶端建立新文件準備存儲來自網絡的數(shù)據(jù)
2.
客戶端連接服務器
3.
客戶端通過網絡接受服務器數(shù)據(jù)并進行數(shù)據(jù)解包
4.
客戶端將數(shù)據(jù)寫入緩沖區(qū)
5.
客戶端從緩沖區(qū)把數(shù)據(jù)寫入客戶本地文件
|
總結
:
事實上
java
的開發(fā)環(huán)境為我們提供大多數(shù)的編程接口
,
為我們簡化了開發(fā)工作量
.
我們通過
java
的
IO
接口所提供的文件
,
數(shù)據(jù)包裝器等接口非常方便的解決了我們上面的開發(fā)工作量
.
同時在
java
的
net
接口所提供的套接字也使得基于連接的數(shù)據(jù)接受和發(fā)送成為非常容易的工作
.
posted on 2007-01-18 23:58
苦笑枯 閱讀(273)
評論(0) 編輯 收藏 所屬分類:
Java