利用线程池下载百度地图瓦片图(代码片段)

秋夜雨巷 秋夜雨巷     2022-11-01     639

关键词:

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

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


/**
 * 线程池下载图片
 */
class BDTask implements Runnable 
    //正常百度地图String link = "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x=x&y=y&z=z&styles=pl&udt=20170712&scaler=1&p=1";
    //午夜蓝版
    static String link ="http://api0.map.bdimg.com/customimage/tile?&x=x&y=y&z=z&udt=20180711&scale=1&ak=0F7691e465f5d7d161a4771f48ee38ff&styles=t%3Awater%7Ce%3Aall%7Cc%3A%23021019%2Ct%3Ahighway%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Ahighway%7Ce%3Ag.s%7Cc%3A%23147a92%2Ct%3Aarterial%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Aarterial%7Ce%3Ag.s%7Cc%3A%230b3d51%2Ct%3Alocal%7Ce%3Ag%7Cc%3A%23000000%2Ct%3Aland%7Ce%3Aall%7Cc%3A%2308304b%2Ct%3Arailway%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Arailway%7Ce%3Ag.s%7Cc%3A%2308304b%2Ct%3Asubway%7Ce%3Ag%7Cl%3A-70%2Ct%3Abuilding%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Aall%7Ce%3Al.t.f%7Cc%3A%23857f7f%2Ct%3Aall%7Ce%3Al.t.s%7Cc%3A%23000000%2Ct%3Abuilding%7Ce%3Ag%7Cc%3A%23022338%2Ct%3Agreen%7Ce%3Ag%7Cc%3A%23062032%2Ct%3Aboundary%7Ce%3Aall%7Cc%3A%231e1c1c%2Ct%3Amanmade%7Ce%3Ag%7Cc%3A%23022338%2Ct%3Apoi%7Ce%3Aall%7Cv%3Aoff%2Ct%3Aall%7Ce%3Al.i%7Cv%3Aoff%2Ct%3Aall%7Ce%3Al.t.f%7Cv%3Aon%7Cc%3A%232da0c6";;
    static String rootDir = "d:/mybaidumapdownload1";

    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 startDownload() 
        ThreadPoolExecutor threadPoolExecutor = null;
        long start = 0L;
        for(Level c : Level.values())
            int z = c.getLevel();
            int xmin = c.getX_min();
            int xmax = c.getX_max();
            int ymin = c.getY_min();
            int ymax = c.getY_max();
            start = System.currentTimeMillis();    //开始时间
            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();    //此种方法会一直创建线程导致死机
                        /*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结束
        

        threadPoolExecutor.shutdown();   //关闭线程池
        while (!threadPoolExecutor.isTerminated()) 
             //所有任务被执行完毕时继续往下执行
        System.out.println("-------用时-------:" + (System.currentTimeMillis() - start));
        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 file = new File(rootDir+"/tiles/" + z + "/" + i + "/" + j + ".jpg");
            if (!file.getParentFile().exists()) 
                file.getParentFile().mkdirs();
            
            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++;
            
        
    


/**
 * 枚举类型,这里所有的等级和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;
    

源码

openlayers6结合geoserver实现地图矢量瓦片(附源码下载)(代码片段)

...现地图矢量瓦片2.源代码demo下载效果图如下:实现思路:利用Geoserver发布矢量切片服务,然后openlayers调用矢量瓦片服务渲染加载,geoserver发布矢量服务步骤自行百度搜索相关教程,网上很多。最后,通过地图点击事件交互,实... 查看详情

c#拼接地图瓦片

为了在AE程序中使用离线的电子地图,思路如下:利用下载工具下载地图切片,然后利用C#进行切片拼接成一张图片,最后使用ArcMap进行地理配准,然后发布成ArcGISServer切片服务供程序使用。今天讲的就是如何利用C#拼接切片。1... 查看详情

百度与谷歌地图瓦片组织方式对比(代码片段)

百度是从中心点经纬度(0,0)度开始计算瓦片,在第1级时百度将世界地图分为4块。中心点右上部分(中国地区)占1块。 谷歌是从左上角经纬度(-180,90)度开始计算瓦片,在第1级时谷歌将世界地图分为1块。 在第2级时,百度地... 查看详情

百度地图的瓦片规则参数

...,如切片的起点、分辨率等等。参考技术A现在很多地图下载器就可以下载的呀,比如水经注地图下载器就可以的呀,下载的瓦片还可以支持百度api的二次开发! 查看详情

关于天地图的瓦片下载

关于天地图的瓦片组织规则在这篇博客里面已经讲解得很清楚了https://www.cnblogs.com/The-SEA/p/4364074.html天地图的底图是原点在左上角,满足长宽比1:2的矩形地图。而OSM(OpenStreetMap)等地图则是正方形。百度地图的原点位于整幅地... 查看详情

openlayers3应用:加载百度离线瓦片地图

...对一定区域地图加载应用,比如一个县的地图,可以采用下载百度瓦片地图,在服务器或者本机单独部署的方式进行。本篇主要讲述如何使用openlayers3调用下载的百度离线瓦片地图。瓦片地图下载器,网上有很多,在此不做详细... 查看详情

openlayers应用:加载百度离线瓦片

...对一定区域地图加载应用,比如一个县的地图,可以采用下载百度瓦片地图,在服务器或者本机单独部署的方式进行。本篇主要讲述如何使用openlayers3调用下载的百度离线瓦片地图。瓦片地图下载器,网上有很多,在此不做详细... 查看详情

qt之加载百度离线地图(webkit和webengine)

...件。二.原理1.制作百度离线地图API原理就是将在线的JSAPI下载到本地,屏蔽掉验证,并将API中引用的资源替换为本地资源,包括将在线瓦片替换为本地离线瓦片。详见:百度离线地图JSAPIV3.02.下载瓦片地图百度地图是由一张张正... 查看详情

离线地图解决方案:加载瓦片地图

...。针对局域网内网内脱离要脱离互联网访问的应用,需要下载这些主流厂商的瓦片数据。网上有很多地图下载器软件可以下载地图瓦片,可以通过各种方式获取到这些地图厂商的瓦片数据。加载高德离线瓦片数据:650)this.width=650... 查看详情

地图瓦片整体介绍

...。地图数据会以json等格式分块地传输过去,在浏览器端利用前端框架将地图在显示出来。在这个基础上,你必须懂得canvas。整个展示的过程对点线面的渲染有很严格的规定。总体来说,矢量瓦片的数据传输量少,服务器压力小... 查看详情

多时相地图瓦片简单设想

...数列关系,所以应该对每一帧都带有独立的时间记录。在利用这个视频瓦片的时候,应用程序可根据关键帧解析出所有时间的影像帧。如果是用于对外提供多时相的可视化影像地图服务,那么这将是一种极大节省数据传输量的方... 查看详情

基于mysql+node.js+leaflet的离线地图展示,支持百度谷歌高德腾讯地图

...歌、高德、腾讯地图。主要功能如下:实现了地图瓦片图下载、存储。目前支持存储至MySQLNode.js服务调用MySQL中的瓦片图Leaflet展示地图展示效果如下:2.地图瓦片下载工具及配置工具下载链接:http://pan.baidu.com/s/1qYoHj4K密码:ehgh工具... 查看详情

百度离线地图发布源代码

百度离线地图发布源代码一键离线地图发布(工具软件下载)  使用教程谷歌离线地图发布 教程手机离线地图发布——Oruxmaps制作发布高清卫星离线地图说明:1. 当前版本支持百度电子地图瓦片和百度卫星地图瓦... 查看详情

supermap系列——gis数据之地图瓦片

...需要服务器出图,导致服务器压力大,出图慢等问题,而利用瓦片地图技术可以很好的解决这个问题。那什么是地图瓦片呢?地图瓦片是包含了一系列比例尺、一定地图范围内的地图切片文件。地图瓦片按照金字塔结构组织,每... 查看详情

谷歌离线地图包下载

谷歌离线地图包下载一键离线地图发布(工具软件下载)  使用教程百度离线地图发布  教程 手机离线地图发布——Oruxmaps制作发布高清卫星离线地图谷歌离线地图发布API解析说明:1. 当前版本支持谷歌电... 查看详情

百度地图开发_离线

本文记录注意事项:0)经实践知,下载离线瓦片TL最为好用;因5.6+版本QWebKit被废弃,建议采用新组件进行开发1)离线下载时请依照需求选择,街道图最为常用。2)离线地图按照等级划分,如果下载全中国请勾选4-17级,一般3-15级即... 查看详情

基于openlayers实现导航地图上(起/终)点的交互式图标显示(代码片段)

目录1、准备 2、瓦片地图显示3、增加矢量图层4、利用click实现鼠标点击效果    在常见的导航软件中,往往都存在标记起/止点的需求。毕竟路径规划中的重要传入参数就是起止点坐标。在常用的不管是移动端还是PC端࿰... 查看详情

线程池(代码片段)

...取出来线程使用。使用完成之后把线程归还给集合。合理利用线程池能够带来三个好处:1.降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个 查看详情