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

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

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++;
            }
        }
    }
	}

包装一下方便使用
在这里插入图片描述
其中,baiduMap.properties的link为下载地址,rootDir为存储地址

BaiDuMapDownloadByThreadPool.java代码如下
  package com.autumn.dao;

import java.io.File;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**

  • 下载图片
    */
    public class BaiDuMapDownloadByThreadPool {
    public static void main(String[] args)
    throws Exception {

     //根据properties文件配置url和存储路径
     Properties properties = new Properties();
     File file = new File("classpath:baiduMap.properties");
     InputStream inputStream = BaiDuMapDownloadByThreadPool.class.getResourceAsStream("baiduMap.properties");
     //判断是否有此文件
     if (inputStream!=null) {
         properties.load(inputStream);
         String link = properties.getProperty("link");
         if (link!=null&&!link.isEmpty()){
             BDTask.link=link;
         }
         String rootDir = properties.getProperty("rootDir");
         if (rootDir!=null&&!rootDir.isEmpty()){
             BDTask.rootDir=rootDir;
         }
     }
    
     BDTask.startDownload();
    

    }
    }

/**

/**

  • 枚举类型,这里所有的等级和xy轴数据为扬州的地图

  • 等级 x最小 x最大 y最小 y最大
    */
    enum Level {
    Level_3(3, 1, 1, 0, 0),
    Level_4(4, 3, 3, 0, 0),
    Level_5(5, 6, 6, 1, 3),
    Level_6(6, 12, 12, 3, 3),
    Level_7(7, 25, 25, 7, 7),
    Level_8(8, 50, 50, 14, 14),
    Level_9(9, 101, 101, 28, 29),
    Level_10(10, 202, 203, 57, 59),
    Level_11(11, 404, 407, 115, 119),
    Level_12(12, 808, 814, 230,239),
    Level_13(13, 1617, 1629, 460, 480),
    Level_14(14, 3234, 3259, 920, 960),
    Level_15(15, 6469, 6518, 1840, 1920),
    Level_16(16, 12939, 13036, 3680, 3850),
    Level_17(17, 25878, 26073, 7360, 7670),
    Level_18(18, 51757, 52146, 14720,15400),
    Level_19(19, 103514, 104292, 29400,30700);

     private int level;
     private int x_min;
     private int x_max;
     private int y_min;
     private int y_max;
    
     Level(int level, int x_min, int x_max, int y_min, int y_max) {
         this.level = level;
         this.x_min = x_min;
         this.x_max = x_max;
         this.y_min = y_min;
         this.y_max = y_max;
     }
    
     public int getLevel() {
         return level;
     }
    
     public int getX_min() {
         return x_min;
     }
    
     public int getX_max() {
         return x_max;
     }
    
     public int getY_min() {
         return y_min;
     }
    
     public int getY_max() {
         return y_max;
     }
    

    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值