全國各省市縣級邊界範圍及其中心城區查詢(調用百度地圖)

做它的原因
接了老師一個項目,老師要我先去收集各個省市縣級的邊界座標以及中心城區範圍,然後老師要用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

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