Uri的四个主要组成部分:
[scheme:][//authority][path][?query][#fragment]
scheme:指http、file、content等;
authority:在ContentProvider中有使用,没有找到对应的中文翻译;
path:在authority之后的相对路径;
query:查询语句。
fragment:主要指id。
举例:
1. Uri :http://www.google.com/getDetails?id=123
对应的四部分:
secheme:http, authority: www.google.com, path : /getDetails, query: id=123
2,. Uri : content://com.fx.demo:200/system/etc/#28
对应的四部分:
secheme:content, authority: com.fx.demo:200, path : /system/etc, query: null, fragment:28
使用URL对象建立连接,获取要下在的文件的大小,然后将文件按照大小均分给4个线程,每个线程下载完分配给自己的那部分,即完成了任务。
涉及的要点:1. 每个线程使用url.openStream()创建一个InputStream,他们可以相互独立的读取url所指向的文件,同时进行比特流的传输;
2. 下载文件时,指定一个byte[]来缓存临时文件,这个数组不要太大,否则可能出现从流中读不满长度为数组大小的字节。
下面看一看代码:
package com.yxf.uridemos;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
public class UriDemos {
public static void main(String[] args) {
// TODO Auto-generated method stub
final String URL_ADDRESS = "http://images.china-pub.com/ebook3770001-3775000/3770325/ch01.pdf";
final int DOWNLOAD_THREAD_NUM = 4;
final String OUT_FILE_NAME = "out_put.pdf";
InputStream[] inputArray = new InputStream[DOWNLOAD_THREAD_NUM];
RandomAccessFile[] outputArray = new RandomAccessFile[DOWNLOAD_THREAD_NUM];
try {
URL url = new URL(URL_ADDRESS);
long fileLength = getFileLength(url);
long numPerThread = fileLength / DOWNLOAD_THREAD_NUM;
long left = fileLength % DOWNLOAD_THREAD_NUM;
for(int i = 0 ; i < DOWNLOAD_THREAD_NUM;i++) {
inputArray[i] = url.openStream();
outputArray[i] = new RandomAccessFile(OUT_FILE_NAME, "rw");
if(i == DOWNLOAD_THREAD_NUM - 1) {
new DownloadThread(i * numPerThread, (i + 1) * numPerThread + left, inputArray[i], outputArray[i]).start();
}else {
new DownloadThread(i * numPerThread, (i + 1) * numPerThread, inputArray[i], outputArray[i]).start();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static long getFileLength(URL url) {
try {
URLConnection connection = url.openConnection();
return connection.getContentLength();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
}
package com.yxf.uridemos;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
public class DownloadThread extends Thread{
private long start;
private long end;
private InputStream inputStream;
private RandomAccessFile output;
private long count;
private final int BUF_LEN = 128;
public DownloadThread(long start, long end, InputStream inputStream, RandomAccessFile output){
this.start = start;
this.end = end;
this.inputStream = inputStream;
this.output = output;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
inputStream.skip(start);
output.seek(start);
byte[] buff = new byte[BUF_LEN];
long contentLen = end - start;
long times = contentLen / BUF_LEN + 20;
int hasRead = 0;
for(int i = 0; i < times; i++) {
hasRead = inputStream.read(buff);
count += hasRead;
if(hasRead < 0) {
break;
}
output.write(buff, 0, hasRead);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if (inputStream != null) {
inputStream.close();
}
if(output != null) {
output.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}