欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Java之多线程断点下载的实现,java多线程断点下载,RandomAccess

来源: javaer 分享于  点击 9091 次 点评:276

Java之多线程断点下载的实现,java多线程断点下载,RandomAccess


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() &amp;&amp; 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());                        }                    }                }            }        }    }}
相关栏目:

用户点评