网络图片下载 多线程

来源:互联网 发布:淘宝上购买 森海塞尔 编辑:程序博客网 时间:2024/06/09 16:39

单线程下载

        String uri = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489320877777&di=0602ac45c01a727564917f688e3d4ad2&imgtype=0&src=http%3A%2F%2Fpic41.nipic.com%2F20140521%2F18810499_233249416000_2.jpg";        // 构造URL        URL url = new URL(uri);        // 打开连接        URLConnection con = url.openConnection();        // 输入流        InputStream is = con.getInputStream();        // 1K的数据缓冲        byte[] bs = new byte[1024];        // 读取到的数据长度        int len;        File f = new File("F:\\a.jpg");        // 输出的文件流        OutputStream os = new FileOutputStream(f);        // 开始读取 ,每次不能确定读取多少个字节        while ((len = is.read(bs)) != -1) {          os.write(bs, 0, len);        }        // 完毕,关闭所有链接        os.close();        is.close();

从网络上下载的文件read(byte[]) 无法保证每次读取多少个字节,这儿可能是根据流量分的,从本地读取的时候 可以保证每次能读取到的字节数就是1024,所以可以设置数组长度为图片大小os.available(),j就不用while了
多线程下载
好处:可以一边下载一边往文件里写入数据,不用等待?提问?问啥要用多线程呀

ConnectionManagerImpl 用于打开连接

public class ConnectionManagerImpl implements ConnectionManager {    @Override    public Connection open(String url) throws ConnectionException {        try {            URL uri = new URL(url);            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();            conn.setRequestMethod("GET");            conn.setConnectTimeout(1000);            Connection connImpl = new ConnectionImpl(conn);            return connImpl;        } catch (IOException e) {            // TODO Auto-generated catch block        }        return null;    }}

ConnectionImpl 用于得到字节数,读取某段字节

public class ConnectionImpl implements Connection{    private HttpURLConnection conn;     private InputStream is;    public ConnectionImpl(HttpURLConnection conn) {        try {            this.conn = conn;            is = conn.getInputStream();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    @Override    public byte[] read(int startPos, int endPos) throws IOException {          if(is==null){              return null;          }          is.skip(startPos);          int len = endPos-startPos;          byte[] bt = new byte[len];          byte[] temp = new byte[1024];          int m=0;          int nowLen=0;          while((m=is.read(temp))>0){              if(nowLen+m>len){                  System.arraycopy(temp, 0, bt, nowLen, len-nowLen);                  break;              }              System.arraycopy(temp, 0, bt, nowLen, m);              nowLen += m;          }          return bt;    }    @Override    public int getContentLength() {        if(conn==null){            return 0;        }        try {            int length=conn.getContentLength();            return length;        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return 0;    }    @Override    public void close() {        if(is!=null){            try {                is.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}

下载 DownLoadThread

public class DownloadThread extends Thread{    Connection conn;    int startPos;    int endPos;    byte[] reads;    public DownloadThread( Connection conn, int startPos, int endPos){        this.conn = conn;               this.startPos = startPos;        this.endPos = endPos;    }    public void run(){          try {             reads=conn.read(startPos, endPos);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

多线程下载 DownloadThreadImpl

public class FileDownloader {    String url;    DownloadListener listener;    ConnectionManager cm;    public FileDownloader(String _url) {        this.url = _url;    }    public void execute(){        // 在这里实现你的代码, 注意: 需要用多线程实现下载        // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码        // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定)        // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有        //     线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。        // 具体的实现思路:        // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度        // 2. 至少启动3个线程下载,  注意每个线程需要先调用ConnectionManager的open方法        // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组        // 3. 把byte数组写入到文件中        // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法        // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。        Connection conn1 = null;        Connection conn2 = null;        Connection conn3 = null;        try {            File f = new File("F:\\百度.jpg");            FileOutputStream os=null;            try {                if(!f.exists()){                    f.createNewFile();                }else{                    f.delete();                }                 os = new FileOutputStream(f,true);            } catch (FileNotFoundException e) {                // TODO Auto-generated catch block                e.printStackTrace();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            conn1 = cm.open(this.url);            int length = conn1.getContentLength();              conn2 = cm.open(this.url);            conn3 = cm.open(this.url);            DownloadThread thread1=new DownloadThread(conn1,0,length/3);            DownloadThread thread2=new DownloadThread(conn2,length/3,(length/3)*2);            DownloadThread thread3 =new DownloadThread(conn3,(length/3)*2,length-1);            thread1.start();            thread2.start();            thread3.start();            StringBuilder add = new StringBuilder();            while(true){                if(!thread1.isAlive()&&add.indexOf("1")<0){                    try {                        os.write(thread1.reads);                        add.append("1");                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                if(!thread2.isAlive()&&add.indexOf("2")<0&&add.indexOf("1")==0){                    try {                        os.write(thread2.reads);                        add.append("2");                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                if(!thread3.isAlive()&&add.indexOf("3")<0&&add.indexOf("12")==0){                    try {                        os.write(thread3.reads);                        add.append("3");                        os.flush();                        os.close();                        listener.notifyFinished(true);                        break;                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        } catch (ConnectionException e) {                       e.printStackTrace();        }finally{            if(conn1 != null){                conn1.close();            }            if(conn2!=null){                conn2.close();            }            if(conn3!=null){                conn3.close();            }        }    }    public void setListener(DownloadListener listener) {        this.listener = listener;    }    public void setConnectionManager(ConnectionManager ucm){        this.cm = ucm;    }    public DownloadListener getListener(){        return this.listener;    }}

测试

public void testDownload() {        String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489320877777&di=0602ac45c01a727564917f688e3d4ad2&imgtype=0&src=http%3A%2F%2Fpic41.nipic.com%2F20140521%2F18810499_233249416000_2.jpg";        FileDownloader downloader = new FileDownloader(url);        ConnectionManager cm = new ConnectionManagerImpl();        downloader.setConnectionManager(cm);        DoloadListenerImpl lister = new DoloadListenerImpl();        downloader.setListener(lister);        downloader.execute();        // 等待多线程下载程序执行完毕        while (!downloader.getListener().getIsFinished()) {            try {                System.out.println("还没有下载完成,休眠五秒");                //休眠5秒                Thread.sleep(5000);            } catch (InterruptedException e) {                              e.printStackTrace();            }        }        System.out.println("下载完成!");    }
0 0
原创粉丝点击