网络图片下载 多线程
来源:互联网 发布:淘宝上购买 森海塞尔 编辑:程序博客网 时间: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
- 网络图片下载 多线程
- 多线程图片下载
- 多线程图片下载
- 网络图片下载
- 网络图片下载
- 多线程批量图片下载器
- 多线程:图片下载案例
- 多线程:图片下载案例
- JAVA程序网络图片下载
- 网络flickr图片下载
- iOS-网络图片下载
- 网络通信之图片下载
- 网络图片下载与缓存
- 网络图片下载工具类
- 网络图片下载设置
- 简单的网络图片下载
- 猫猫学iOS(五十五)多线程网络之图片下载框架之SDWebImage
- AJ学IOS(55)多线程网络之图片下载框架之SDWebImage
- i2c信号的ACK与NACK
- MVC中几种常用ActionResult
- LeetCode:123. Best Time to Buy and Sell Stock I
- Linux发展史
- Echarts3之html2canvas下载图表(后续生成PDF)
- 网络图片下载 多线程
- app开发好了你还不得不了解ASO
- SDWebImage源码解读之干货大总结
- Swift的GCD详解
- 算法之直接选择排序
- Javascript中的 “&” 和 “|” 你知多少?
- 第一次
- java四种引用包括强引用,软引用,弱引用,虚引用。
- Huffman树