多线程正常百度地图瓦片获取、卫星图瓦片、道路图瓦片、卫星图道路图拼接。

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 {
        BDTask.startDownload();
    }
}

/**
 * 线程池下载图片
 */
class BDTask implements Runnable {
//    正常百度地图
//    static 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://shangetu1.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46&udt=20170712";//卫星图
//static String link = "http://online2.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=sl&udt=20170712";//道路图

    //午夜蓝版
//    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 = "f:/ganshuweixin";

    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结束
                System.out.println("x坐标已经下载到:"+i);
            }   //循环X结束
        }
        System.out.println("第:"+c+"缩放等级已经下载完毕---------------------------------------------------------------------------");


        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(500);
            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) {
            e.printStackTrace();
            System.out.println("z:"+z+"x:"+i+"y:"+j+"下载失败!");
            synchronized (c) {
                fail++;
            }
        }
    }
}

/**
 * 枚举类型
 * 等级 x最小 x最大 y最小 y最大
 */
enum Level {
//    Level_3(3, 1, 1, 0, 0),
//    Level_4(4, 1, 4, 0, 2),
//    Level_5(5, 3, 8, 0, 4),
//    Level_6(6, 7, 15, 0, 7),
//    Level_7(7, 19, 24, 7, 11),
//    Level_8(8, 39, 47, 14, 21),
//    Level_9(9, 78, 93, 29, 41),
//    Level_10(10, 184, 184, 58, 81);
//    Level_11(11, 370, 370, 116, 161);
//    Level_12(12, 670, 707, 42,431);
//    Level_13(13, 1476, 1477, 466, 642);
    Level_14(14, 2758, 2758, 932, 1283);
//    Level_15(15, 5897, 5897, 2361, 2361);
//    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;
    }
}

分为三种下载方式:正常地图、卫星图、道路图。(都是各种资料找的)。还有个一午夜蓝版,额,要用的可以用。

这个是下载的本地地址

这里填写具体需要下载的缩放级别、横坐标最小最大值、纵坐标最小最大值。

具体坐标,可以在网上下载相关工具,然后看它里面对应的坐标。(如果找不到也可以留言,发给你)

 注意:代码里面中下载失败的提示是正确的,但是具体下载到那里了,提示不正确,可以直接观察下载的文件。

由于网络、死机等原因,可能会断开下载,如果人工检查从哪里断开很麻烦,需要检查各个文件夹下的文件个数。提供一个检验文件夹数量工具类:

import java.io.File;

public class Num {
    public static void main(String[] ages)
    {
        //检查文件夹下图片个数
        for(int i=2512;i<=2955;i++){
            File file=new File("D:\\result\\tiles\\14\\"+i);
            String files[];
            files=file.list();
            int num = files.length;
            if(num!=352){
                System.out.println(i);
            }
        }




    }
}

提供一个检查下载文件是否连续的工具类,

import java.io.File;

public class Islianxu{
    public static void main(String[] args){
        //    检查图片文件名称连续
        File file = new File("G:\\weitile\\tiles\\10\\181");
        File[] tempList = file.listFiles();

        for(int i = 0;i < tempList.length; i++) {
            if(Integer.valueOf(tempList[i].getName().substring(0,tempList[i].getName().length()-4))-i!=10){
                System.out.println(i);
            }
        }
    }

}

有时候需求是需要在卫星图上显示、道路信息,但是我没有找到,能直接请求得到这种图的接口地址(应该没有),所以解决办法是将道路图以水印的方式和卫星图相结合。

具体图片打水印的方式,我是使用thumbnailator框架的,虽然说很久没有更新的,但是比较简单好用。

package com.example.thumbnail;
import net.coobird.thumbnailator.Thumbnails;

import javax.imageio.ImageIO;
import java.awt.*;
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 {
        BDTask.startDownload();
    }
}

/**
 * 线程池下载图片
 */
class BDTask implements Runnable {

    int i;  //x坐标
    int j;  //y坐标
    int z;  //缩放级别

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

    public BDTask(int i, int j, int z) {
        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(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结束
                System.out.println("x坐标已经下载到:"+i);
            }   //循环X结束
        }
        System.out.println("第:"+c+"缩放等级已经下载完毕---------------------------------------------------------------------------");


        threadPoolExecutor.shutdown();   //关闭线程池
        while (!threadPoolExecutor.isTerminated()) {
        }     //所有任务被执行完毕时继续往下执行
        System.out.println("-------用时-------:" + (System.currentTimeMillis() - start));
        System.out.println("共下载:   " + c + "   张");
        System.out.println("失败:   " + fail + "   张");
    }

    public void run() {
        try {
            int x=0;
            int y=0;

            net.coobird.thumbnailator.geometry.Position ab=  new net.coobird.thumbnailator.geometry.Position() {
                @Override
                public Point calculate(int enclosingWidth, int enclosingHeight, int width, int height, int insetLeft,
                                       int insetRight, int insetTop, int insetBottom) {
                    return new Point(x, y);
                }
            };
            //            创建文件夹,因为创建结合图片的时候,框架不会自动创建文件夹
            File file = new File("d:/result/tiles/" + z + "/" + i );
            if (!file.exists()) {
                file.mkdirs();
            }
            Thumbnails.of(new File("f:/ganshuweixin/tiles/" + z + "/" + i + "/" + j + ".jpg"))
                    .size(256, 256)
                    .watermark(ab, ImageIO.read(new File("f:/gaoshudaolu/tiles/" + z + "/" + i + "/" + j + ".jpg")), 1)
                    .outputQuality(1.0d)
                    .toFile(new File("d:/result/tiles/" + z + "/" + i + "/" + j + ".jpg"));
            synchronized (fail) {
                c++;
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("z:"+z+"x:"+i+"y:"+j+"图片结合失败!");
            synchronized (c) {
                fail++;
            }
        }
    }
}

/**
 * 枚举类型
 * 等级 x最小 x最大 y最小 y最大
 */
enum Level {
    //    Level_3(3, 1, 1, 0, 0),
//    Level_4(4, 1, 4, 0, 2),
//    Level_5(5, 3, 8, 0, 4),
//    Level_6(6, 7, 15, 0, 7),
//    Level_7(7, 15, 29, 1, 14),
//    Level_8(8, 31, 58, 2, 27),
//    Level_9(9, 62, 115, 5, 54),
//    Level_10(10, 124, 230, 10, 108),
//    Level_11(11, 249, 459, 21, 216),
//    Level_12(12, 499, 918, 42,431);
//    Level_13(13, 1256, 1478, 466, 642),
//    Level_14(14, 2512, 2955, 932, 1283),
//    Level_15(15, 5025, 5910, 1864, 2565);
//    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);
//甘肃
//    Level_6(6, 9, 12, 3, 6),
//    Level_7(7, 19, 24, 7, 11),
//    Level_8(8, 39, 47, 14, 21),
//    Level_9(9, 78, 93, 29, 41),
//    Level_10(10, 157, 185, 58, 81),
//    Level_11(11, 314, 370, 116, 161),
//    Level_12(12, 628, 739, 233,321),
//    Level_13(13, 1256, 1478, 466, 642),
    Level_14(14, 2758, 2758, 932, 1283);
//    Level_15(15, 5897, 5897, 1864, 2565);

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

将之前下载的卫星图和道路图结合。

注意:thumbnailator将两张图片结合后,输出的文件夹路径如果不存在,不会自动创建文件夹。所以需要预先创建文件夹,比如代码中:

最后:有一些卫星图在某些缩放等级下,会显示该地没有卫星图,但是对应的有道路图,这是正常现象,百度地图中也存在该种情况。

我下载的深度是全国4-12,20多万张。甘肃6-15,80多万张。层级越深,增长越快,时间大概7个小时左右。

下载后需要检查,下载图片有些没有下载对,或者没有下载,需要手动重新下载。

以上是经验总结,有需要可以留言

猜你喜欢

转载自blog.csdn.net/qq_31293575/article/details/81866521