由於Linux操作系統的興起和Java語言的日漸成熟
使用Java語言實現一個跨平台的
外觀一致的下載工具軟件已成為可能
網絡螞蟻是大家非常熟知的下載工具軟件
我采用Java語言實現了類似網絡螞蟻的基本功能的軟件Jants
本文介紹了一些技術實現要點
單線程直接獲取網絡文件
單線程直接獲取網絡文件的關鍵點是獲取網絡文件
以確定基本方法的正確性
它的初始代碼的內容比較簡單
可以利用HTTP的基本知識進行設計
它的基本原理是
連接網絡地址
打開連接並獲取輸入流
從輸入流中讀取數據
實現代碼(測試過程中使用的)如下
int data;//從輸入流中獲取數據
URL url=new URL(
);
//創建連接的地址
HttpURLConnection connection=url
openConnection();
//打開連接
int responsCode=connection
getResponseCode();
//返回Http的響應狀態碼
InputStream input=connection
getInputStream();
//獲取輸入流
System
out
println(
responseCode:
+responseCode);
While((data=input
read())!=
)
System
out
println(data);
//將獲取的數據打到屏幕顯示出來
單線程斷點續傳
大家常常有這樣的體會:下載一個幾十兆的文件時突然斷線
結果前功盡棄
可以使用斷點續傳解決這個問題
基本原理
這裡主要介紹一下斷點續傳的原理
斷點續傳的原理很簡單
只是在HTTP請求上和一般的下載有所不同
所謂斷點續傳
也就是要從文件已經下載的地方開始繼續下載
所以
在客戶端傳給Web服務器的時候
要多加一條信息——下載的起始位置
且服務器返回的HTTP狀態代碼也從
轉變為
上述要點
可以使用Java語言中的HttpURLConnection類中的setRequestProperty()方法來設置
斷點續傳的關鍵步驟
實現提交斷點續傳下載的起始位置
Java的Net包中提供了這種功能
代碼如下
URL url = new URL(
;);
HttpURLConnection httpConnection=(HttpURLConnection) url
openConnection();
//設置斷點續傳的開始位置
(
RANGE
bytes=
);
//設置請求信息
(
GET
/down
zip HTTP/
);
//設置接受信息
(
Accept
image/gif
image/x
xbitmap
application/
msword
*/*
);
//設置連接信息
(
Connection
Keep
Alive
);
//獲得輸入流
InputStream input = ();
從輸入流中取出的字節流
就是down
zip文件從
字節開始的字節流
保存獲得的字節流到文件中
由於文件的下載涉及到斷點續傳
因此
在保存文件的時候
需要對文件進行隨機讀寫
特別是在多線程下載的過程中
需要在寫文件之前在文件中定位
在Java的IO包中的RandomAccessFile類可以滿足這種設計需求
該類在文件中定位指針時
用到的方法是seek(Long)
操作相當簡單
假設從
字節處開始保存文件
代碼如下
RandomAccess oSavedFile = new RandomAccessFile(
down
zip
rw
);
//創建隨機文件
long nPos =
;
//定位文件指針到nPos位置
oSavedFile
seek(nPos);
byte[] b = new byte[
];
int nRead;
//從輸入流中讀入字節流
然後寫到文件中
while((nRead=input
read(b
)) >
)
{ //input為網絡輸入流
oSavedFile
write(b
nRead);
}
保存已經下載的文件的長度值
由於在每次斷開連接時都要保存已下載文件的長度
且應進行永久保存
因此將它保存到文件介質中
這裡采用的是對象序列化的方法——將要保存的內容序列化到一個臨時文件中
代碼如下
long nStart;
//記錄已經下載的字節數
File tempFile=new File(
donwzip
tmp
);
//創建臨時文件
FileOutputStream file=new FileOutputStream(tempFile);
//創建文件輸出流
ObjectOutputStream serialize=new ObjectOutputStream(file)
//創建文件序列化流
serialize
writeObject(nStart);//序列化
serialize
flush();
//刷新序列化流
file
close();
//關閉文件輸出流
serialize
close();
//關閉序列化流
多線程的斷點續傳
加入斷點續傳以後
下載速度還沒能得到提高
為防止已下載文件數據的丟失
也為提高網絡文件的下載速度
可在其中加入多線程
雖然前兩步已經基本實現
似乎再加入多線程時應該比較容易
但是並非如此
在多線程的編程過程中
需要考慮到線程的同步與互斥
由於是多線程進行斷點續傳
還要考慮記錄多個斷點位置
且記錄斷點位置時也要考慮同步互斥等問題
所有這些都使得這一步比較復雜
同步的考慮
同步的基本思想是避免多個線程訪問同一個資源時出現問題
由於多線程對同一個文件資源進行讀寫
因此
為了避免出現錯誤
要進行讀寫控制——即同步
Java中使用synchronized實現線程之間的同步
Java是面向對象的語言
它的資源是以對象的形式表現的
因此
Java同步機制的作用就是力圖避免對
對象
的訪問沖突
對需要同步的方法或代碼段進行標記以實現同步
需要用到關鍵字synchronized
系統使用synchronized關鍵字聲明的方法就是為其設置特殊的標記
這個標記起著信號量的作用
每當調用該方法時
Java的運行系統都將進行檢查
以確認此標記的狀態
看相應的代碼是否已經被調用執行
如沒有執行
系統將把這個內部標記授予調用代碼的線程
方法運行結束後
標記被釋放
在標記被釋放之前
任何其它的對象不得調用此方法
主要的同步代碼如下(在下載數據保存入文件中時使用)
public synchronized int write(byte[] b
int nStart
int len){
int n=
;
try{
rf
write(b
nStart
len);
//調用另一個類的方法
向文件中寫入數據
n=len;
}catch(IOException ioe){
ioe
printStackTrace();
}
return n;
}
在保存已下載的字節數時
由於多個斷點位置在不同的線程中記錄
所以必須在所有線程都結束時才能保存
為此
解決的辦法是再開出一個線程
用以持續監測是否所有的線程都已經結束
若結束
保存所有的斷點位置
否則
繼續監測
同樣
在文件下載的線程中
需要設置標志位以記錄線程是否結束
基本代碼如下(在監測線程中使用)
stop=false;
while(!stop){
if(Utility
bStop[
] && Utility
bStop[
] && Utility
bStop[
] && Utility
bStop[
] && Utility
bStop[
]){
System
out
println(
Serialize
);
Utility
serializeOut();
//調用序列化函數以保存斷點位置於文件中
javaants
setStopFalse();
javaants
setStartTrue();
stop=true;
}
斷點數據的記錄
筆者使用的是一個靜態數組以記錄斷點位置
由於有多個斷點位置
可采用一個函數進行統一保存
public static void serializeOut(){
try{
File tempFile=new File(getTempFileName()+
+
tmp
);
FileOutputStream file=new FileOutputStream(tempFile);
ObjectOutputStream serialize=new ObjectOutputStream(file);
for(int i=
;i<
;i++){
serialize
writeObject(String
valueOf(nStart[i]));
serialize
writeObject(String
valueOf(nStop[i]));
}
serialize
flush();
file
close();
serialize
close();
}catch(Exception e){
System
out
println(e
toString());
}
}
圖形界面
該文件下載系統的圖形界面與流行下載軟件——網絡螞蟻很相似
圖形界面的實現
使用了Swing包
限於篇幅
這裡不再贅述
Jants的圖形界面如圖
和圖
所示
圖
Jants主界面
圖
Jants下載過程中的界面
發布
使用jar命令將所有的文件下載系統的
class文件打包為javaants
jar文件
並在其中加入Menifest
mf文件
指定Main
Class
打包代碼
jar cfv *
* javaants
jar
運行代碼
javaw
classpath javaants
jar Main
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26485.html