码迷,mamicode.com
首页 > 编程语言 > 详细

利用线程池下载百度地图瓦片图

时间:2018-04-09 18:59:51      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:get   adp   时间   pen   fail   .sh   通过   unit   map   

  继上一文章,百度地图离线功能,这里主要讲述下载瓦片图具体方法。

  1.利用全能电子地图下载带水印的瓦片图。其中文件夹路径为tile/层级/x/y.jpg,如下图所示,全能电子地图1.9下载的百度地图瓦片图是一个个黑点。

技术分享图片

  2.根据图片url下载图片,根据URL获取HttpURLConnection, 根据HttpURLConnection获取输入流InputStream ,在用输出流OutputStream out = new FileOutputStream(file);将字节写入文件即可。代码如下:

/**
 * 下载图片
 */
public class BaiDuMapDownload {
    static volatile Integer c = 0;//成功数
    static volatile Integer fail = 0;//失败数量
public static void main(String[] args) throws Exception { String link = "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=20170712&scaler=1&p=1"; int z = 19;//层级 int xmin = 103514;//x最小值 int xmax = 104292;//x最大值 int ymin = 29400;//y最小值 int ymax = 30700;//y最大值 for (int i = xmin; i <= xmax; i++) { //循环X for (int j = ymin; j <= ymax; j++) { //循环Y try {
URL url
= new URL(link.replace("{x}", i + "").replace("{y}", j + "").replace("{z}", z + "")); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(100); conn.connect(); InputStream in = conn.getInputStream(); File dir = new File("d:/mybaidumapdownload1/tiles/" + z + "/" + i); if (!dir.exists()) { dir.mkdirs(); } File file = new File("d:/mybaidumapdownload1/tiles/" + z + "/" + i + "/" + j + ".jpg"); if (!file.exists()) { file.createNewFile(); } OutputStream out = new FileOutputStream(file); byte[] bytes = new byte[1024 * 20]; int len = 0; while ((len = in.read(bytes)) != -1) { out.write(bytes, 0, len); } out.close(); in.close(); //System.out.println("已成功下载:" + z + "_" + i + "_" + j + ".jpg"); c++; } catch (Exception e) { System.out.println(e.getMessage()); fail++; }
}
//循环Y结束 } //循环X结束 Thread.sleep(1000); System.out.println("共下载: " + c + " 张"); System.out.println("失败: " + fail + " 张"); } }

  3.通过上面的代码就可以下载百度图片,但是很明显,上面代码是单线程,而且会IO阻塞,百度地图下载到第19级时有将近一百万的瓦片图。下面是线程池ThreadPoolExecutor

优化下代码。本来两天才能下完的图时间缩减一天会感觉很棒。

/**
 * 线程池下载图片
 */
class BDTask implements Runnable{
    String link;
    int i;  //x坐标
    int j;  //y坐标
    int z;  //缩放级别

    static volatile Integer c = 0;//成功数
    static volatile Integer fail = 0;//失败数量

    public BDTask(String link, int i, int j, int z) {
        this.link = link;
        this.i = i;
        this.j = j;
        this.z = z;

    }
    public static void main(String[] args)
            throws Exception {
        String link = "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=20170712&scaler=1&p=1";
        int z = 12;  //层级
        int xmin = 808; //x最小值
        int xmax = 814;  //x最大值
        int ymin = 230;  //y最小值
        int ymax = 239;  //y最大值
        //创建线程池,corePoolSize两条线程,最大存在四条线程,大于corePoolSize小于MaxmumPoolSize的线程等待空闲时间为500毫秒,任务队列LinkBlockingQueue不写时的默认值为Integer默认值.
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,4,500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
        for (int i = xmin; i <= xmax; i++) {   //循环X
            for (int j = ymin; j <= ymax; j++) {    //循环Y
                threadPoolExecutor.execute(new BDTask(link,i,j,z));
                //new Thread(new BDTask(link,i,j,z)).start();    //此种方法会一直创建线程导致死机
            }    //循环Y结束
        }   //循环X结束
        threadPoolExecutor.shutdown();   //关闭线程池
        while (!threadPoolExecutor.isTerminated()){}     //一直循环等到所有任务被执行完毕时继续往下执行
        System.out.println("共下载:   " + c + "   张");
        System.out.println("失败:   " + fail + "   张");
    }

    public void run() {
        try {
            URL url = new URL(link.replace("{x}", i + "").replace("{y}", j + "").replace("{z}", z + ""));
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(100);
            conn.connect();
            InputStream in = conn.getInputStream();
            File dir = new File("d:/mybaidumapdownload1/tiles/" + z + "/" + i);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File file = new File("d:/mybaidumapdownload1/tiles/" + z + "/" + i + "/" + j + ".jpg");
            if (!file.exists()) {
                file.createNewFile();
            }
            OutputStream out = new FileOutputStream(file);
            byte[] bytes = new byte[1024 * 20];
            int len = 0;
            while ((len = in.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            }
            out.close();
            in.close();
            synchronized (fail) {
                c++;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            synchronized (c) {
                fail++;
            }
        }
    }
}

源码

利用线程池下载百度地图瓦片图

标签:get   adp   时间   pen   fail   .sh   通过   unit   map   

原文地址:https://www.cnblogs.com/aeolian/p/8761430.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!