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