RandomAccessFile类:
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组,光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/ 写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数 组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
下面有RandomAccessFile实现安卓下的断点下载的demo。
服务器端可以用tomcat模拟,将被下载的测试文件放入webApp/ROOT目录下即可。
先给出java借助HttpURLConnection类实现的多线程下载代码:
- public class MultiThread {
- private static int threadCount = 3;
- private static long blockSize;
- private static int runningThreadCount;
- public static void main(String[] args) throws Exception {
- String path = "http://10.0.67.172/test.exe";
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setConnectTimeout(5000);//超时时间
- int code = conn.getResponseCode();
- System.out.println(code);
- if(code / 100 == 2){
- int size = conn.getContentLength();//获取资源文件的长度
- System.out.println("请求资源大小:" + size);
- blockSize = size / threadCount;//将资源文件分为多少块,没一块的大小
- runningThreadCount = threadCount;
- long startIndex = 0;
- long endIndex = 0;
- //开启若干个子线程去实现多线程的下载
- for(int i = 0; i < threadCount; i++){
- startIndex = i * blockSize;
- endIndex = (i + 1) * blockSize - 1;
- if(i == threadCount-1){
- endIndex = size - 1;
- }
- System.out.println("开启线程:" + i + ";" + "开始位置:" + startIndex + ":" + "结束位置:" + endIndex);
- new DownThread(path, startIndex, endIndex, i).start();
- }
- }
- }
- private static class DownThread extends Thread{
- private String path;
- private long startIndex;
- private long endIndex;
- private int threadId;
- public DownThread(String path, long startIndex, long endIndex, int threadId) {
- super();
- this.path = path;
- this.startIndex = startIndex;
- this.endIndex = endIndex;
- this.threadId = threadId;
- }
- @Override
- public void run() {
- try {
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setReadTimeout(5000);
- conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);//设置服务器上的文件的读取位置
- int code = conn.getResponseCode();
- if(code / 100 == 2){
- InputStream is = conn.getInputStream();
- File file = new File("temp.exe");
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- raf.seek(startIndex);
- System.out.println("第" + threadId + "个文件的开始位置:" + String.valueOf(startIndex));
- int len = 0;
- byte[] buffer = new byte[1024];
- while ((len = is.read(buffer)) != -1){
- raf.write(buffer, 0, len);//写文件
- }
- raf.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
断点下载的原理就是将上次文件下载的位置保存为临时文件,当完全下载完毕时再删除。
- public class MultiThread {
- private static int threadCount = 3;
- private static long blockSize;
- private static int runningThreadCount;
- public static void main(String[] args) throws Exception {
- String path = "http://10.0.67.172/test.rar";
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setConnectTimeout(5000);//超时时间
- int code = conn.getResponseCode();
- System.out.println(code);
- if(code / 100 == 2){
- int size = conn.getContentLength();//获取资源文件的长度
- System.out.println("请求资源大小:" + size);
- blockSize = size / threadCount;//将资源文件分为多少块,没一块的大小
- runningThreadCount = threadCount;
- long startIndex = 0;
- long endIndex = 0;
- for(int i = 0; i < threadCount; i++){
- startIndex = i * blockSize;
- endIndex = (i + 1) * blockSize - 1;
- if(i == threadCount-1){
- endIndex = size - 1;
- }
- System.out.println("开启线程:" + i + ";" + "开始位置:" + startIndex + ":" + "结束位置:" + endIndex);
- new DownThread(path, startIndex, endIndex, i).start();
- }
- }
- }
- private static class DownThread extends Thread{
- private String path;
- private long startIndex;
- private long endIndex;
- private int threadId;
- public DownThread(String path, long startIndex, long endIndex, int threadId) {
- super();
- this.path = path;
- this.startIndex = startIndex;
- this.endIndex = endIndex;
- this.threadId = threadId;
- }
- @Override
- public void run() {
- int total = 0;
- try {
- File positionFile = new File(threadId + ".txt");
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- //接着上次的文件继续下载
- if(positionFile.exists() && positionFile.length() > 0){
- FileInputStream fis = new FileInputStream(positionFile);
- BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
- //获取当前线程上次下载的总大小是多少
- String lasttotalstr = reader.readLine();
- int lastTotal = Integer.valueOf(lasttotalstr);
- System.out.println("上次线程下载的总大小:" + lastTotal);
- startIndex += lastTotal;
- total += lastTotal;
- fis.close();
- }
- conn.setReadTimeout(5000);
- conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);//设置服务器上的文件的读取位置
- int code = conn.getResponseCode();
- if(code / 100 == 2){
- InputStream is = conn.getInputStream();
- File file = new File("temp.rar");
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- raf.seek(startIndex);
- System.out.println("第" + threadId + "个文件的开始位置:" + String.valueOf(startIndex));
- int len = 0;
- byte[] buffer = new byte[1024];
- while ((len = is.read(buffer)) != -1){
- RandomAccessFile rf = new RandomAccessFile(positionFile, "rwd");
- raf.write(buffer, 0, len);//写文件
- total += len;
- rf.write(String.valueOf(total).getBytes());
- rf.close();
- }
- is.close();
- raf.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally{
- synchronized (DownThread.class) {
- System.out.println("线程" + threadId + "下载完毕了");
- runningThreadCount--;
- if (runningThreadCount < 1) {
- System.out.println("所有的线程都工作完毕了。删除临时记录的文件");
- for (int i = 0; i < threadCount; i++) {
- File f = new File(i + ".txt");
- System.out.println(f.delete());
- }
- }
- }
- }
- }
- }
- }
来源: http://www.phpxs.com/code/1002211/