全国各省市县级边界范围及其中心城区查询(调用百度地图)

做它的原因
接了老师一个项目,老师要我先去收集各个省市县级的边界座标以及中心城区范围,然后老师要用R语言去画图调用。然后我就直接百度去下载现成的数据,但是老师说不行,要最新的,以前网上的数据都是以前的。现在好多行政区县都已经更新了。近几年的数据还没有。所以只能自己做了。也能确保数据的准确性。
特地强调。确实echarts可以画地图。但是里面的边界数据并不精确。如果你需要做的项目是边界必须特别精确的,而是最新的。你得自己获取。echarts里的china.js数据已经老了。

这里写图片描述
这里写图片描述
前期准备
首先我们需要城市信息。哪里来这些城市的信息呢?第一个想到的是百度文科直接下载,第二个是爬虫。但是老师说,还是爬虫好,让我把中国天气预报网上的数据爬下来。那里的城市信息准确。然后我就用八爪鱼爬了(懒得自己写爬虫。。。)。爬下来以后发现。数据不对。天气预报网上的地方确实是最新的。但是天气预备有个特点。相邻区域就不一定会报。比如上海市中心就包含了好几个区。其次用风景区代替城市。导致我查找的地址不准确。做出来画的地图不对。所以,我还是去百度文库里下了一份2016年的省市县级的名称。
这里写图片描述
不过数据不准确还是得做处理。可以看见,首先,各个省没有分开。意思是我省的数据也是需要的。然后应该纯在省,空,空这样的数据元。还有安庆这里就写了安庆。有些百度是可以直接出来的。但是还有的不行比如巢湖。这个城市你在查找边界范围的时候不输入巢湖市出不来。所以我们需要对这些数据做处理。把省级分开。把名字补全,那些结尾不是区,镇,县,街道,旗(蒙古的比较多)的数据,尾部补上市,便于查找。把重复的这里写图片描述给规整,市级是三沙市就是三沙市,县级下面不应该再来个三沙市。
当然这么做还有个前提,要读取excel文件。
我这里采用的是个包pio-3.16。具体方式是参考 http://blog.csdn.net/sinat_29581293/article/details/52122191 它的。
然后展示下,我修改数据的文件

package dealWithSource;

import java.io.File;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.io.InputStream;
import java.util.ArrayList;

import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.ss.usermodel.Cell;

import org.apache.poi.ss.usermodel.Row;

import org.apache.poi.ss.usermodel.Sheet;

import org.apache.poi.ss.usermodel.Workbook;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
 * 
 * @描述:测试excel读取
 * 
 */

public class importExcel
{
    /** 总行数 */
    private int totalRows= 0;
    /** 总列数 */
    private int totalCells= 0;
    /** 错误信息 */
    private String errorInfo;

    /** 构造方法 */
    public importExcel()
    {
    }

    public int getTotalRows()
    {
        return totalRows;
    }

    public int getTotalCells()
    {
        return totalCells;
    }

    public String getErrorInfo()
    {
        return errorInfo;
    }

    public boolean validateExcel(String filePath)
    {
        /** 检查文件名是否为空或者是否是Excel格式的文件 */
        if(filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath)))
        {
            errorInfo= "文件名不是excel格式";
            return false;
        }
        /** 检查文件是否存在 */
        File file= new File(filePath);
        if(file == null || !file.exists())
        {
            errorInfo= "文件不存在";
            return false;
        }
        return true;
    }

    public List<List<String>> read(String filePath)
    {
        List<List<String>> dataLst= new ArrayList<List<String>>();
        InputStream is= null;
        try
        {
            /** 验证文件是否合法 */
            if(!validateExcel(filePath))
            {
                System.out.println(errorInfo);
                return null;
            }
            /** 判断文件的类型,是2003还是2007 */
            boolean isExcel2003= true;
            if(WDWUtil.isExcel2007(filePath))
            {
                isExcel2003= false;
            }
            /** 调用本类提供的根据流读取的方法 */
            File file= new File(filePath);
            is= new FileInputStream(file);
            dataLst= read(is,isExcel2003);
            is.close();
        }catch (Exception ex)
        {
            ex.printStackTrace();
        }finally
        {
            if(is != null)
            {
                try
                {
                    is.close();
                }catch (IOException e)
                {
                    is= null;
                    e.printStackTrace();
                }
            }
        }
        /** 返回最后读取的结果 */
        return dataLst;
    }

    public List<List<String>> read(InputStream inputStream, boolean isExcel2003)
    {
        List<List<String>> dataLst= null;
        try
        {
            /** 根据版本选择创建Workbook的方式 */
            Workbook wb= null;
            if(isExcel2003)
            {
                wb= new HSSFWorkbook(inputStream);
            }else
            {
                wb= new XSSFWorkbook(inputStream);
            }
            dataLst= read(wb);
        }catch (IOException e)
        {

            e.printStackTrace();
        }
        return dataLst;
    }

    private List<List<String>> read(Workbook wb)
    {
        List<List<String>> dataLst= new ArrayList<List<String>>();
        /** 得到第一个shell */
        Sheet sheet= wb.getSheetAt(0);
        /** 得到Excel的行数 */
        this.totalRows= sheet.getPhysicalNumberOfRows();
        /** 得到Excel的列数 */
        if(this.totalRows >= 1 && sheet.getRow(0) != null)
        {
            this.totalCells= sheet.getRow(0).getPhysicalNumberOfCells();
        }
        /** 循环Excel的行 */
        for(int r= 0; r < this.totalRows; r++)
        {
            Row row= sheet.getRow(r);
            if(row == null)
            {
                continue;
            }
            List<String> rowLst= new ArrayList<String>();
            /** 循环Excel的列 */
            for(int c= 0; c < this.getTotalCells(); c++)
            {
                Cell cell= row.getCell(c);
                String cellValue= "";
                if(null != cell)
                {
                    // 以下是判断数据的类型
                    switch(cell.getCellType())
                    {
                        case HSSFCell.CELL_TYPE_NUMERIC: // 数字
                            cellValue= cell.getNumericCellValue() + "";
                            break;
                        case HSSFCell.CELL_TYPE_STRING: // 字符串
                            cellValue= cell.getStringCellValue();
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                            cellValue= cell.getBooleanCellValue() + "";
                            break;
                        case HSSFCell.CELL_TYPE_FORMULA: // 公式
                            cellValue= cell.getCellFormula() + "";
                            break;
                        case HSSFCell.CELL_TYPE_BLANK: // 空值
                            cellValue= "";
                            break;
                        case HSSFCell.CELL_TYPE_ERROR: // 故障
                            cellValue= "非法字符";
                            break;
                        default:
                            cellValue= "未知类型";
                            break;
                    }
                }
                rowLst.add(cellValue);
            }
            /** 保存第r行的第c列 */
            dataLst.add(rowLst);
        }
        return dataLst;
    }

    // 到处表格
    public void write(List<List<String>> source)
    {
        // 第一步,创建一个webbook,对应一个Excel文件
        HSSFWorkbook wb= new HSSFWorkbook();
        // 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
        HSSFSheet sheet= wb.createSheet("省市");
        // 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
        HSSFRow row= sheet.createRow((int) 0);
        // 第四步,创建单元格,并设置值表头 设置表头居中
        HSSFCellStyle style= wb.createCellStyle();
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式

        HSSFCell cell= row.createCell((short) 0);
        cell.setCellValue("省");
        cell.setCellStyle(style);
        cell= row.createCell((short) 1);
        cell.setCellValue("市");
        cell.setCellStyle(style);
        cell= row.createCell((short) 2);
        cell.setCellValue("县");
        cell.setCellStyle(style);

        // 第五步,写入实体数据 实际应用中这些数据从数据库得到,
        List<List<String>> list= source;
        List<String> temp=new ArrayList<String>();
        for(int i= 0; i < list.size(); i++)
        {
            row= sheet.createRow((int) i + 1);
            temp=list.get(i);
            // 第四步,创建单元格,并设置值
            for(int j=0;j<temp.size();j++)
            {
                row.createCell((short) j).setCellValue(temp.get(j));
            }

        }
        // 第六步,将文件存到指定位置
        try
        {
            FileOutputStream fout= new FileOutputStream("E:/模版.xls");
            wb.write(fout);
            fout.close();
        }catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception
    {
        importExcel poi= new importExcel();
        // List<List<String>> list = poi.read("d:/aaa.xls");
        List<List<String>> list= poi.read("E:/QQ文件/中国各省市邮政编码、电话区号大全.xls");
        if(list != null)
        {
            for(int i= 0; i < list.size(); i++)
            {
                System.out.print("第" + (i) + "行");
                List<String> cellList= list.get(i);
                for(int j= 0; j < cellList.size(); j++)
                {
                    // System.out.print(" 第" + (j + 1) + "列值:");
                    System.out.print("    " + cellList.get(j));
                }
                System.out.println();
            }

        }

    }

}

class WDWUtil
{
    public static boolean isExcel2003(String filePath)
    {
        return filePath.matches("^.+\\.(?i)(xls)$");
    }

    public static boolean isExcel2007(String filePath)
    {
        return filePath.matches("^.+\\.(?i)(xlsx)$");
    }
}
package dealWithSource;

import java.util.ArrayList;
import java.util.List;

//处理表单。把表格调节成标准格式 (省,市,县)
public class createTable
{

    public static void main(String[] args)
    {
        importExcel poi= new importExcel();
        // 省 市 县 
        List<List<String>> result= new ArrayList<List<String>>();
        try
        {
            List<List<String>> list= poi.read("E:/全国县级以上城市行政区划表.xls");

            if(list != null)
            {
                //上一个省的名字,用于把省分隔开
                String previousProvince="";
                for(int i= 0; i < list.size(); i++)
                {
                    List<String> cellList= list.get(i);
                    List<String> res= new ArrayList<String>();

                    String province=cellList.get(0).trim();
                    String city= dealWith(cellList.get(1).trim());
                    String country=dealWith(cellList.get(2).trim());

                    if(!previousProvince.equals(province))
                    {
                        previousProvince=province;
                        //当遇到一个新的省的时候,那一行,就一个省字段,市,县为空
                        res.add(province);
                        res.add("");
                        res.add("");
                        result.add(res);
                        res= new ArrayList<String>();
                    }
                    //省和市的照常添加
                    res.add(province);
                    res.add(city);
                    if(country.equals("")||country.equals(city))
                    {
                        res.add("");// 县为空
                    }
                    else
                    {
                        res.add(country);
                    }
                    System.out.println(province+" "+city+" "+country);
                    result.add(res);
                }

            }
            poi.write(result);

        }catch (Exception e)
        {
            poi.write(result);
            e.printStackTrace();
        }
    }

    //给没加市的城市加上市,便于查找相应地区
    public static String dealWith(String result)
    {
        result=result.trim();
        if(result==null||result.equals(""))
            return result;
        if(result.substring(result.length()-1).equals("镇")||result.substring(result.length()-1).equals("县")||result.substring(result.length()-1).equals("街道")||result.substring(result.length()-1).equals("区")||result.substring(result.length()-1).equals("旗")||(result.length()>4&&result.substring(result.length()-3).equals("自治州"))||(result.length()>2&&result.substring(result.length()-2).equals("街道")))
            return result;
        else
        {
            return result.trim()+"市";
        }
    }
}

然后这个文件用java application运行下,就可得到我要的初始数据模版了。
这里写图片描述
这里可以说明我为什么要先人为处理数据,而不是放到后面获取边界时一起处理。因为,减少bug的判断。万一后面出了很多bug要改,至少我能排除,我这里没有bug。也能确保后期万一我处理失败,这里每个数据元名字不会重复的再做处理。

然后我们就进入了工作阶段了跑数据,获取市中心以及边界。
什么是行政中心?不应该是简单的获取边界后取一个重心就当作城市中心的。而是应该以行政中心为准。大多数行政中心独有个特点。就是都是人民政府,如浙江省人民政府,这是省级的,到市级就有杭州市人民政府,县级有县级的人们政府。街道没有人民政府。自治州的是政府。开发区的只有管理委员会。当然,当你跑完数据后你也会发现一些特例,但是觉得不会多。到时候百度查找修改下就好了。
然后怎么获取数据呢?通过百度http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition 获取座标
代码如下 先去百度地图获取个ak,然后下载个数据包
这里写图片描述
导入到程序里。(其实,这个不用服务器,直接用java application也可以运行出来的)

package service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

public class Parser_Tool
{
    /**
     * post 获取 rest 资源
     * 
     * @param url
     * @param name_value_pair
     * @return
     * @throws IOException
     */
    public static String doPost(String url, List<NameValuePair> nameValuePair) throws IOException
    {
        String body= "{}";
        DefaultHttpClient httpclient= new DefaultHttpClient();
        try
        {
            HttpPost httpost= new HttpPost(url);
            httpost.setEntity(new UrlEncodedFormEntity(nameValuePair,StandardCharsets.UTF_8));
            HttpResponse response= httpclient.execute(httpost);
            HttpEntity entity= response.getEntity();
            body= EntityUtils.toString(entity);
        }finally
        {
            httpclient.getConnectionManager().shutdown();
        }
        return body;
    }

    /**
     * get 获取 rest 资源
     * 
     * @param url
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String doGet(String url) throws ClientProtocolException, IOException
    {
        String body= "{}";
        DefaultHttpClient httpclient= new DefaultHttpClient();
        try
        {
            HttpGet httpget= new HttpGet(url);
            HttpResponse response= httpclient.execute(httpget);
            HttpEntity entity= response.getEntity();
            body= EntityUtils.toString(entity);
        }finally
        {
            httpclient.getConnectionManager().shutdown();
        }
        return body;
    }

    //把x,y座标区分开
    public static String[] dealWith(String result)
    {
        int x= result.indexOf("\"lng\":");
        int y= result.indexOf(",\"lat\":");
        int end= result.indexOf("},\"precise");
        if(x == -1)
        {
            String[] answer= { "", "" };
            return answer;
        }
        String xs= result.substring(x + 6,y);
        String ys= result.substring(y + 7,end);
        String[] answer= { xs, ys };
        return answer;

    }

}

这是个获取座标的工具类。
然后我们就解决边界了。通过我是通过js调用百度地图api去获取的。
代码如下
这是jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>获取地区轮廓线</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3">
</script>
<style type="text/css">
body {
    font-size: 13px;
    margin: 10px
}

#container {
    width: 800px;
    height: 500px;
    border: 1px solid gray
}
</style>
</head>
<body>
    <div id="container"></div>
    <br /> 输入省、直辖市或县名称:
    <script type="text/javascript">
        var map = new BMap.Map("container");
        map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5);
        map.addControl(new BMap.NavigationControl({
            type : BMAP_NAVIGATION_CONTROL_SMALL
        }));
        map.enableScrollWheelZoom();
        function getBoundary() 
        { 
            var bdary = new BMap.Boundary();
            var name = document.getElementById("districtName").value;
            bdary.get(name, function(rs) { //获取行政区域
                map.clearOverlays(); //清除地图覆盖物       
                var count = rs.boundaries.length; //行政区域的点有多少个
                for (var i = 0; i < count; i++) {
                    var ply = new BMap.Polygon(rs.boundaries[i], {
                        strokeWeight : 2,
                        strokeColor : "#ff0000"
                    }); //建立多边形覆盖物
                    map.addOverlay(ply); //添加覆盖物
                    map.setViewport(ply.getPath()); //调整视野         
                }
                var answer=document.getElementById("result");
                answer.value=rs.boundaries;
            });
        }
        setTimeout(getBoundary,1);
        setTimeout(a,5000);
    //  var i=0;
        function a()
        {
            //if(document.getElementById("result").value!="")
                document.getElementById("fom").submit();
            //else
            //{
        //      setTimeout(a,200);
        //  }
        }
    </script>
    <form id="fom" action="excel" method="post">
    <input type="text" id="districtName" name="districtName" style="width: 80px" value="${result}">
    <input id="result" name="result" value=""></input>
    <input onclick="getBoundary()" type="button" id="start" value="获取轮廓线"/>
    <input type="submit" value="提交"/>
    </form>

</body>
</html>

我这里是定时。5秒后自动提交数据。理由是,搜索需要时间。最晚5秒内肯定能好。不能设置一获取数据就传递到servlet里去,因为缺失存在一些找不到边界的。可能是百度地图里没有边界,或者省政府名字不正确,简写等导致的。这时候如果设置一获取数据就传递就会卡主。不动,除非手工按。所以我采用设置5秒自动提交。万一没有数据也不等了。直接提交。说明那个城市是有问题的。

package servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import service.WebExcel;

@WebServlet("/excel")
public class servlce extends HttpServlet
{
    static WebExcel work;
    static boolean first=true;
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {

        String local= request.getParameter("result");
        //String now= new String(request.getParameter("districtName").getBytes("iso-8859-1"), "utf-8"); 
        String next="";//下一个查找的城市
        if(first)
        {
            first=false;
            work= new WebExcel();
        }
        next= work.doWork(local);
        if(next == "over")
            return; 
        request.setAttribute("result",next);
        request.getRequestDispatcher("baiduMap.jsp").forward(request,response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        doPost(request,response);
    }
}
package service;

import java.util.ArrayList;
import java.util.List;

import Dao.CountryDao;


public class WebExcel
{
    int i = 0;
    static List<List<String>> list;
    static List<List<String>> result;
    String place;
    Excel poi;
    CountryDao dao;
    // 1.地理编码服务,即根据地址来查经度纬度
    String ak = "你百度获取的ak";
    String url1 = "http://api.map.baidu.com/geocoder/v2/?address=";
    String url2 = "&output=json&ak=" + ak;

    public WebExcel()
    {
        result = new ArrayList<List<String>>();
        dao = new CountryDao();
        poi = new Excel();
        list = poi.readExcel();
    }

    // 为每个城市添加边境范围座标
    public String doWork(String border)
    {
        try
        {
            if (list != null && i < list.size())
            {
                // 每一列加范围座标
                if (i != 0)
                {
                    List<String> temp = new ArrayList<String>();
                    String province = list.get(i).get(0);
                    String city = list.get(i).get(1);
                    String country = list.get(i).get(2);

                    temp.add(province);// 放入省市
                    temp.add(city);// 放入市区
                    temp.add(country);// 放入县
                    place = "";
                    // 获取中心点座标
                    if (city.equals(""))
                    {
                        place = province;// 放入省
                    }else if (country.equals(""))
                    {
                        place = city;// 放入市
                    }else
                    {
                        if (city.substring(city.length() - 1).equals("市"))
                            place = city.substring(0, city.length() - 1) + country;// 放入县
                        else
                            place = city + country;
                    }
                    if (place.length() >= 3)
                    {
                        String end = place.substring(place.length() - 3);
                        if (end.equals("自治州"))
                        {
                            place += "政府";
                        }
                        if (end.equals("开发区"))
                        {
                            place += "管理委员会";
                        }else
                        {
                            place += "人民政府";
                        }
                    }
                    //获取中心点的x,y
                    String[] answer = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));
                    temp.add(answer[0]);
                    temp.add(answer[1]);
                    System.out.println(place+": x:"+answer[0]+" y:"+answer[1]);

                    // x,y区分处理
                    String[] arr = border.split(",|;");
                    String x = "";
                    String y = "";
                    for(int i = 0; i < arr.length; i++)
                    {
                        if (i % 2 == 0)
                        {
                            if (i != arr.length - 2)
                                x += arr[i] + ",";
                            else
                            {
                                x += arr[i];
                            }
                        }else
                        {
                            if (i != arr.length - 1)
                                y += arr[i] + ",";
                            else
                            {
                                y += arr[i];
                            }
                        }
                    }
                    temp.add(x);// 放入边界范围
                    temp.add(y);
                    result.add(temp);
                    // dao.addExcel(temp);
                }else
                {
                    // 默认导入的是同一个数据源
                    result = dao.getDate();
                    i=result.size();
                }
                System.out.println("边界范围" + ":"+border);
                i++;
                if (i >= list.size())
                {
                    dao.addAllExcel(result);
                    // dao.fillBorder(result);
                    return "over";
                }

                //返回下一个省
                if(list.get(i).get(1).equals(""))
                    return list.get(i).get(0);
                //返回下一个市
                if(list.get(i).get(2).equals(""))
                    return list.get(i).get(0)+list.get(i).get(1);
                else
                {
                    if (list.get(i).get(1).substring(list.get(i).get(1).length() - 1).equals("市"))
                        place = list.get(i).get(0)+list.get(i).get(1).substring(0, list.get(i).get(1).length() - 1) + list.get(i).get(2);// 放入县
                    else
                        place = list.get(i).get(0)+list.get(i).get(1) + list.get(i).get(2);
                    return place;
                }

            }
            return "over";
        }catch(Exception e)
        {
            e.printStackTrace();
            dao.addAllExcel(result);
            return "over";
        }
    }
}

我当时是分开做实验的。获取地址和边界。所以获取边界的时候我是采用另一种方式读取excelde 。用的是jxl这里写图片描述
导入个这个包就好了

package service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Excel
{
    File file = new File("E:模版.xls");
    File write = new File("E:");
    List<List<String>> library = new ArrayList<List<String>>();
    int i = 0, j = 0;

    public Excel()
    {
    }

    // 去读Excel的方法readExcel,该方法的入口参数为一个File对象
    public List<List<String>> readExcel()
    {
        try
        {
            // 创建输入流,读取Excel
            InputStream is = new FileInputStream(file.getAbsolutePath());
            // jxl提供的Workbook类
            Workbook wb = Workbook.getWorkbook(is);
            // Excel的页签数量
            int sheet_size = wb.getNumberOfSheets();
            for(int index = 0; index < sheet_size; index++)
            {
                // 每个页签创建一个Sheet对象
                Sheet sheet = wb.getSheet(index);
                // sheet.getRows()返回该页的总行数
                for(int i = 0; i < sheet.getRows(); i++)
                {
                    // sheet.getColumns()返回该页的总列数
                    List<String> temp = new ArrayList<String>();
                    for(int j = 0; j < sheet.getColumns(); j++)
                    {
                        String cellinfo = sheet.getCell(j, i).getContents();
                        temp.add(cellinfo);
            //          System.out.println(cellinfo);
                    }
                    library.add(temp);
                }
            }
            return library;
        }catch(FileNotFoundException e)
        {
            e.printStackTrace();
        }catch(BiffException e)
        {
            e.printStackTrace();
        }catch(IOException e)
        {
            e.printStackTrace();
        }
        return null;
    }

    // 去读Excel的方法readExcel,该方法的入口参数为一个File对象
    public void writeExcel(List<List<String>> out)
    {
        try
        {
            // 打开文件
            WritableWorkbook book = Workbook.createWorkbook(new File("final.xls"));
            // 生成名为“sheet1”的工作表,参数0表示这是第一页

            WritableSheet sheet = book.createSheet("sheet1", 0);
            // 在Label对象的构造子中指名单元格位置是第一列第一行(0,0),单元格内容为string
            for(int i = 0; i < out.size(); i++)
                for(int j = 0; j < out.get(i).size(); j++)
                {

                    Label label = new Label(j,i, out.get(i).get(j));
                    // 将定义好的单元格添加到工作表中
                    sheet.addCell(label);
                }

            // 写入数据并关闭文件
            book.write();
            book.close();
        }catch(Exception e)
        {
            System.out.println(e);
        }
    }
}

我把结果直接写到数据库的

package Dao;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class BaseDao
{
    DataSource dataSource;
    //构造方法中返回数据源对象
    public BaseDao()
    {
        try
        {
            Context context=new InitialContext();
            dataSource=(DataSource)context.lookup("java:comp/env/jdbc/yanfan");
        }catch(NamingException ne)
        {
            ne.printStackTrace();
        }
    }

    //返回一个连接对象
    public Connection getConnection()throws Exception
    {
        return dataSource.getConnection();
    }
}
package Dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.mysql.jdbc.Statement;

public class CountryDao extends BaseDao
{
    Connection conn;
    PreparedStatement pstmt;
    Statement stmt;
    ResultSet rst;

    // 插入国家信息记录(全部)
    public boolean addAllExcel(List<List<String>> list)
    {
        String sql = "insert into china (province,city,country,xcenter,ycenter,xborders,yborders) values(?,?,?,?,?,?,?)";
        try
        {
            conn = dataSource.getConnection();
            for(int i = 0; i < list.size(); i++)
            {
                pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, list.get(i).get(0));
                pstmt.setString(2, list.get(i).get(1));
                pstmt.setString(3, list.get(i).get(2));
                pstmt.setString(4, list.get(i).get(3));
                pstmt.setString(5, list.get(i).get(4));
                pstmt.setString(6, list.get(i).get(5));
                pstmt.setString(7, list.get(i).get(6));
                pstmt.executeUpdate();
            }
            System.out.println("完成");
            return true;
        }catch(SQLException se)
        {
            se.printStackTrace();
            return false;
        }
    }

    // 添加单个数据元
    public boolean addExcel(List<String> list)
    {
        String sql = "insert into china (province,city,country,xcenter,ycenter,xborders,yborders) values(?,?,?,?,?,?,?)";
        try
        {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(sql);
            for(int i = 0; i < list.size(); i++)
            {
                pstmt.setString(i + 1, list.get(i));
            }
            pstmt.executeUpdate();
            System.out.println("完成");
            return true;
        }catch(SQLException se)
        {
            se.printStackTrace();
            return false;
        }
    }

    // 先检查数据库里已经存在了多少个数据,减少重复输入
    public List<List<String>> getDate()
    {
        List<List<String>> result = new ArrayList<List<String>>();
        String sql = "SELECT * FROM work.china";
        try
        {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(sql);
            rst = pstmt.executeQuery();
            // 获取元数据
            ResultSetMetaData rsmd = rst.getMetaData();
            while(rst.next())
            {
                List<String> temp = new ArrayList<String>();
                // 根据结果表得出的
                for(int i = 0; i < rsmd.getColumnCount(); i++)
                {
                    String conlumnLabel = rsmd.getColumnLabel(i + 1);
                    Object comlumnValue = rst.getObject(conlumnLabel);

                    temp.add("" + comlumnValue);
                }
                result.add(temp);
            }
            return result;
        }catch(SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    // 获取缺失边界点的数据
    public List<List<String>> getBordersDate()
    {
        List<List<String>> result = new ArrayList<List<String>>();
        String sql = "SELECT * FROM work.china where xborders=',' and yborders=''";
        try
        {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(sql);
            rst = pstmt.executeQuery();
            // 获取元数据
            ResultSetMetaData rsmd = rst.getMetaData();
            while(rst.next())
            {
                List<String> temp = new ArrayList<String>();
                // 根据结果表得出的
                for(int i = 0; i < rsmd.getColumnCount(); i++)
                {
                    String conlumnLabel = rsmd.getColumnLabel(i +1);
                    Object comlumnValue = rst.getObject(conlumnLabel);

                    temp.add("" + comlumnValue);
                }
                result.add(temp);
            }
            return result;
        }catch(SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    // 获取缺少中心点的数据
    public List<List<String>> getCenterDate()
    {
        List<List<String>> result = new ArrayList<List<String>>();
        String sql = "SELECT * FROM work.china where xcenter='' and ycenter=''";
        try
        {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(sql);
            rst = pstmt.executeQuery();
            // 获取元数据
            ResultSetMetaData rsmd = rst.getMetaData();
            while(rst.next())
            {
                List<String> temp = new ArrayList<String>();
                // 根据结果表得出的
                for(int i = 0; i < rsmd.getColumnCount(); i++)
                {
                    String conlumnLabel = rsmd.getColumnLabel(i + 1);
                    Object comlumnValue = rst.getObject(conlumnLabel);

                    temp.add("" + comlumnValue);
                }
                result.add(temp);
            }
            return result;
        }catch(SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    // 检查填充边界的数据
    public boolean fillBorder(List<List<String>> list)
    {
        String sql = "update china set country = ?,xborders = ? ,yborders=? where province = ? and city = ? and country = ?";
        try
        {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(sql);
            System.out.println("数量"+list.size());
            for(int i=0;i<list.size();i++)
            {
                pstmt.setString(1, list.get(i).get(7));
                pstmt.setString(2, list.get(i).get(5));
                pstmt.setString(3, list.get(i).get(6));
                pstmt.setString(4, list.get(i).get(0));
                pstmt.setString(5, list.get(i).get(1));
                pstmt.setString(6, list.get(i).get(2));
                System.out.println("加载"+i);
                pstmt.executeUpdate();
                System.out.println("完成"+i);
            }
            System.out.println("完成");
            return true;
        }catch(SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
    }

    // 填充中心
    public boolean fillCenter(List<List<String>> list)
    {
        String sql = "update china set country = ? ,xcenter = ? ,ycenter=? where province = ? and city = ? and country = ?";
        try
        {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(sql);
            for(int i = 0; i < list.size(); i++)
            {
                pstmt.setString(1, list.get(i).get(2));
                pstmt.setString(2, list.get(i).get(3));
                pstmt.setString(3, list.get(i).get(4));
                pstmt.setString(4, list.get(i).get(0));
                pstmt.setString(5, list.get(i).get(1));
                pstmt.setString(6, list.get(i).get(2));
                pstmt.executeUpdate();
            }
            return true;
        }catch(SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
    }
}

记得配置个context.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true">
    <Resource name="jdbc/yanfan" type="javax.sql.DataSource"
        maxActive="40" maxIdle="29" username="root" maxWait="5000"
        driverClassName="com.mysql.jdbc.Driver" password="123456789"
        url="jdbc:mysql://localhost:3306/work" />
</Context>

有了以上代码后就可以开始跑数据了。修改下数据库地方就可以了
这里写图片描述

跑下来可能存在一些数据不正确,比如名字不对,还有可能一些城市已经合并了。因为原数据是近两年的。但是这两年也有些城市发生了变动,所以我只能一个个百度,找到有问题的城市查明原因,去对应修改。修改数据的代码如下

package service;

import java.util.ArrayList;
import java.util.List;

import Dao.CountryDao;

//用于填空的座标
public class FillBorder
{
    List<List<String>> list;
    List<List<String>> result = new ArrayList<List<String>>();
    CountryDao dao = new CountryDao();
    String ak = "你的百度ak";
    String url1 = "http://api.map.baidu.com/geocoder/v2/?address=";
    String url2 = "&output=json&ak=" + ak;
    String place = "";
    int i = 0;// 行
    static boolean end;
    public FillBorder()
    {
        list = dao.getBordersDate();
        System.out.println("边界缺损数量:" + list.size());
    }

    public String doWork(String border)
    {
        try
        {
            if(end)
                return "over";
            String[] arr = border.split(",|;");
            String x = "", y = "";
            List<String> temp = new ArrayList<String>();
            if (i >= list.size())
            {
                dao.fillBorder(result);
                end=true;
                return "over";
            }
            //加入省,市
            for(int j = 0; j < 2; j++)
            {
                temp.add(list.get(i).get(j));
            }
            //加入县
            String country = list.get(i).get(2);
            if ((country.length() > 3 && country.substring(country.length() - 3).equals("街道市"))||(country.length() > 2 && country.substring(country.length() - 2).equals("旗市")))
            {
                country = country.substring(0, country.length() - 1);// 去掉街道名字里的市
            }
            if ((country.length() > 3 && country.substring(country.length() - 3).equals("县图市")))
            {
                country = country.substring(0, country.length() - 2);// 去掉街道名字里的图市
            }
            temp.add(list.get(i).get(2));
            temp.add(list.get(i).get(3));
            temp.add(list.get(i).get(4));
            if ((country.length()>0&&country.substring(country.length() - 1).equals("镇"))||(country.length()>2&&country.substring(country.length()-2).equals("街道")))
            {
                String city = list.get(i).get(1);
                if (city.substring(city.length() - 1).equals("市"))
                {
                    city = city.substring(0, city.length() - 1);
                }
                place += city + country;
                String[] town = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));
                temp.add(town[0]);
                temp.add(town[1]);
                temp.add(country);
                System.out.println(temp.get(7) + " 边界:" + town[0]+" , "+town[1]);
            }else
            {
                for(int i = 0; i < arr.length; i++)
                {
                    if (i % 2 == 0)
                    {
                        x += arr[i];
                        if (i != arr.length - 2)
                        {
                            x += ",";
                        }
                    }else
                    {
                        y += arr[i];
                        if (i != arr.length - 1)
                        {
                            y += ",";
                        }
                    }
                }
                temp.add(x);
                temp.add(y);
                temp.add(country);
                System.out.println(temp.get(2) + " 边界:" + border);
            }
            result.add(temp);
            ++i;
            if (i >= list.size())
            {
                dao.fillBorder(result);
                return "over";
            }
            country = list.get(i).get(2);
            if ((country.length() > 3 && country.substring(country.length() - 3).equals("街道市"))||(country.length() > 2 && country.substring(country.length() - 2).equals("旗市")))
            {
                country = country.substring(0, country.length() - 1);// 去掉街道名字里的市
            }
            if ((country.length() > 3 && country.substring(country.length() - 3).equals("县图市")))
            {
                country = country.substring(0, country.length() - 2);// 去掉街道名字里的图市
            }
            return list.get(i).get(0)+list.get(i).get(1)+country;
        }catch(Exception e)
        {
            e.printStackTrace();
            dao.fillBorder(result);
            return "over";
        }
    }

    public String first()
    {
        String first = list.get(i).get(0)+list.get(i).get(1)+list.get(i).get(2);
        return first;
    }
}
package service;

import java.util.List;

import Dao.CountryDao;

//用于填空的座标
public class FillCenter
{
    List<List<String>> list;
    CountryDao dao = new CountryDao();
    // 1.地理编码服务,即根据地址来查经度纬度
    String ak = "你的百度ak";
    String url1 = "http://api.map.baidu.com/geocoder/v2/?address=";
    String url2 = "&output=json&ak=" + ak;
    String place;

    public FillCenter()
    {
        list = dao.getCenterDate();
        System.out.println("一共有及格没找到中心点" + list.size());
    }

    public boolean doWork()
    {
        try
        {
            for(int i = 0; i < list.size(); i++)
            {
                if (list.get(i).get(2).equals(""))
                {
                    place = list.get(i).get(1);
                    if (place.equals("芒市"))
                        place += "人民政府";
                    if (place.equals("三沙市"))
                        place += "政府";
                    String[] center = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));
                    list.get(i).set(3, center[0]);
                    list.get(i).set(4, center[1]);
                    System.out.println(place + "x:" + center[0] + " y:" + center[1]);
                    continue;
                }
                place = list.get(i).get(2);
                if (place.substring(place.length() - 2).equals("旗市"))
                {
                    place.substring(0, place.length() - 1);// 修改名字,去掉市
                    list.get(i).set(2, place);
                }
                if (place.equals("镇原县"))
                    place += "人民政府政务大厅";
                else if (place.equals("镇平县") || place.equals("樊城区") || place.equals("襄城区") || place.equals("红寺堡区")
                        || place.equals("茂县"))
                    place += "政府";
                else if (place.equals("郧县"))
                    place += "政协";
                else
                    place += "人民政府";
                String[] center = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));
                list.get(i).set(3, center[0]);
                list.get(i).set(4, center[1]);
                System.out.println(place + "x:" + center[0] + " y:" + center[1]);
            }
            return dao.fillCenter(list);
        }catch(Exception e)
        {
            e.printStackTrace();
            dao.fillCenter(list);
            return false;

        }
    }

}
package servlet;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import service.FillBorder;
import service.FillCenter;
@WebServlet("/fillBack")
public class fillBack extends HttpServlet
{
    boolean first=true;
    String city=null;
    FillBorder fill=new FillBorder();
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        String border=request.getParameter("result");
        System.out.println(border);
        if(first)
        {
            //顺手填了中心的座标系
            FillCenter fillCenter=new FillCenter();
            fillCenter.doWork();
            first=false;
            city=fill.first();
        }
        else
        {
            city=fill.doWork(border);
        }
        if(city == "over")
            return; 
        request.setAttribute("result",city);
        request.getRequestDispatcher("fillBorder.jsp").forward(request,response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        doPost(request,response);
    }
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>获取地区轮廓线</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3">
</script>
<style type="text/css">
body {
    font-size: 13px;
    margin: 10px
}

#container {
    width: 800px;
    height: 500px;
    border: 1px solid gray
}
</style>
</head>
<body>
    <div id="container"></div>
    <br /> 输入省、直辖市或县名称:
    <script type="text/javascript">
        var map = new BMap.Map("container");
        map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5);
        map.addControl(new BMap.NavigationControl({
            type : BMAP_NAVIGATION_CONTROL_SMALL
        }));
        map.enableScrollWheelZoom();
        function getBoundary() 
        { 
            var bdary = new BMap.Boundary();
            var name = document.getElementById("districtName").value;
            bdary.get(name, function(rs) { //获取行政区域
                map.clearOverlays(); //清除地图覆盖物       
                var count = rs.boundaries.length; //行政区域的点有多少个
                for (var i = 0; i < count; i++) {
                    var ply = new BMap.Polygon(rs.boundaries[i], {
                        strokeWeight : 2,
                        strokeColor : "#ff0000"
                    }); //建立多边形覆盖物
                    map.addOverlay(ply); //添加覆盖物
                    map.setViewport(ply.getPath()); //调整视野         
                }
                var answer=document.getElementById("result");
                answer.value=rs.boundaries;
            });
        }
        setTimeout(getBoundary,1);
        setTimeout(a,5000);
        function a()
        {
                document.getElementById("fom").submit();
        }
    </script>
    <form id="fom" action="fillBack" method="post">
    <input type="text" id="districtName" name="districtName" style="width: 80px" value="${result}">
    <input id="result" name="result" value=""></input>
    <input onclick="getBoundary()" type="button" id="start" value="获取轮廓线"/>
    <input type="submit" value="提交"/>
    </form>

</body>
</html>

经过这些数据处理就可以了.顺序是先用省,市县去找。然后再用市县去找,最后再用县去找。跑三次,就可以确定这些数据最全了。剩下的得人工修改。因为省市县名字不对。或者城市已经没了,或者简写找不到等导致的。
带吗到数据库里修改(Sql代码)

//删除没有的数据(城市已经被合并了)
delete from china where province=''

//修改数据(因为没有主键,直接修改会报错Error: 1175 SQLSTATE: HY000 (ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE))
//这是先运行下     SET SQL_SAFE_UPDATES = 0;  修改下更新模式就好
update china set xborders=',',yborders='' where province='浙江省'

//查询语句
SELECT * FROM work.china;

//如果数据里面有重复的,可以采用再建立的temp表。和china表一模一样的。
//然后运行sql语句
insert into temp select distanct * from china;
truncate table china;
insert into china select distanct * from temp;
//如果不需要temp了可以人工删除

这里写图片描述
然后就好了。
一下是我的代码。得自己创建下数据库,按照自己的数据库修改下代码context等部分。
http://download.csdn.net/download/qq_33359282/9896354

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章