RandomAccessFile多執行緒下載檔案
阿新 • • 發佈:2019-01-28
原理:
RandomAccessFile能夠隨機讀取檔案,可以讀寫指定位置的內容。所以我們可以開啟n個下載執行緒,每個執行緒專門負責檔案中的一段,當然下載也同樣只是下載對應段的內容。
那怎麼從網路上獲取檔案的特定段呢?
http 1.1提供了分段下載的功能,只需要設定好請求頭就好了,如下:
conn.setRequestProperty(“Range”, “bytes=” + StartPos + “-” + EndPos);
請求的檔案段為 [StartPos, EndPos] 。
RandomAccessFile類的常用方法:
- public RandomAccessFile(File file, String mode)throws FileNotFoundException 構造方法 接收File類的物件,指定操作路徑,但是在設定時需要設定模式:”r”: 只讀、”w”: 只寫、”rw”: 讀寫。
- public RandomAccessFile(String name, String mode) throws FileNotFoundException 構造方法 不再使用File類物件表示檔案,而是直接輸入了一個固定的檔案路徑。
- public void close() throws IOException 關閉操作
- public int read(byte[] b) throws IOException 將內容讀取到一個byte陣列之中
- public final byte readByte() throws IOException 讀取一個位元組
- public final int readInt() throws IOException從檔案中讀取整型資料。
- public void seek(long pos) throws IOException 設定讀指標的位置。
- public final void writeBytes(String s) throws IOException 將一個字串寫入到檔案之中,按位元組的方式處理。
- public final void writeInt(int v) throws IOException 將一個int型資料寫入檔案,長度為4位。
- public int skipBytes(int n) throws IOException 指標跳過多少個位元組。
程式碼實現:
DownloadFile.class
/***
* 要十分注意StartPos 和 EndPos 設定
* ***/
public class DownloadFile {
public final static String FileURL = "http://apache.01link.hk/tomcat/tomcat-7/v7.0.86/bin/apache-tomcat-7.0.86.zip";
public final static int COUNT = 3; //分段數
public static File SaveFile;
public static void main(String[] args) throws IOException {
URL url = new URL(FileURL);
//建立一個連線
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
int code = conn.getResponseCode();
int position = FileURL.lastIndexOf("/");
String fileName = FileURL.substring(position+1); //檔名
System.out.println("file name is :"+fileName);
if(code == 200){
int FileLength = conn.getContentLength(); //獲取檔案長度
System.out.println("檔案總長度為:"+FileLength);
SaveFile = new File("/home/pzs/husin/filedownload/"+fileName);
RandomAccessFile raf = new RandomAccessFile(SaveFile,"rw"); //若沒有該檔案,則自動建立
raf.setLength(FileLength); //設定檔案長度
raf.close();
//分塊大小
int blockSize = FileLength / COUNT;
for(int i=0; i <= COUNT; i++){
int StartPos = i * blockSize;
int EndPos = (i+1) * blockSize - 1;
//最後一條執行緒EndPos = FileLength
if(i == COUNT){
EndPos = FileLength;
}
System.out.println("執行緒" + i + "下載的部分為:" + StartPos +"---" + EndPos);
new DownLoadThread(i,StartPos,EndPos,FileURL,SaveFile).start();
}
}
}
}
DownLoadThread.class
public class DownLoadThread extends Thread{
//執行緒id
private int threadId;
private int StartPos;
private int EndPos;
private String FileURL;
private File SaveFile;
public DownLoadThread(int threadId, int StartPos, int EndPos, String FileURL, File SaveFile){
this.threadId = threadId;
this.StartPos = StartPos;
this.EndPos = EndPos;
this.FileURL = FileURL;
this.SaveFile = SaveFile;
}
@Override
public void run() {
try {
URL url = new URL(FileURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(500);
conn.setRequestMethod("GET");
//請求檔案段
conn.setRequestProperty("Range", "bytes=" + StartPos + "-" + EndPos);
int code = conn.getResponseCode();
//206表示檔案分段請求,而不是整個檔案請求
if(code == 206){
InputStream is = conn.getInputStream();
int len = 0;
byte[] buf = new byte[1024];
RandomAccessFile raf = new RandomAccessFile(SaveFile, "rw");
raf.seek(StartPos);
while((len = is.read(buf)) > 0) {
raf.write(buf, 0, len);
}
is.close();
System.out.println("執行緒" + threadId + "下載完畢!!");
}else{
System.out.println("不支援分段下載");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}