RandomAccessFile多线程下载文件

原理:

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 指针跳过多少个字节。

代码实现:

这里以下载Tomcat 7.086 为例子
url:http://apache.01link.hk/tomcat/tomcat-7/v7.0.86/bin/apache-tomcat-7.0.86.zip

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();
        }
    }
}

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huxiny/article/details/80289198