1.什么是Geocoding?

Geocoding API 是一类简单的HTTP接口,用于提供从地址到经纬度坐标或者从经纬度坐标到地址的转换服务,用户可以使用C# 、C++、Java等开发语言发送HTTP请求且接收JSON、XML的返回数据。

2.功能介绍

Geocoding API包括地址解析和逆地址解析功能。

  • 地理编码:即地址解析,由详细到街道的结构化地址得到百度经纬度信息,且支持名胜古迹、标志性建筑名称直接解析返回百度经纬度。例如:“北京市海淀区中关村南大街27号”地址解析的结果是“lng:116.31985,lat:39.959836”,“百度大厦”地址解析的结果是“lng:116.30815,lat:40.056885”
  • 逆地理编码,即逆地址解析,由百度经纬度信息得到结构化地址信息。例如:“lat:31.325152,lng:120.558957”逆地址解析的结果是“江苏省苏州市虎丘区塔园路318号”。
3.如何使用

百度地图Geocoding API是一套免费对外开放的API,无使用次数限制。使用方法:

第一步:申请ak(即获取密钥),若无百度账号则首先需要注册百度账号

第二步,拼写发送http请求的url,注意需使用第一步申请的ak。

第三步,接收http请求返回的数据(支持json和xml格式)。

以下是一个关于地理编码的简单示例。发送一个地址是“百度大厦”的请求,返回该地址对应的地理坐标。发送请求的url如下:

http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=E4805d16520de693a3fe707cdc962045&callback=showLocation
4.java调用测试
 package addressToGeoTest;

 import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*; public class GetLatAndLngByBaidu { public static void main(String args[]){ String cnAddress="北京市海淀区上地十街10号";
Map<String,String> map = GetLatAndLngByBaidu.getLatitude(cnAddress);
if(null != map){
System.out.println(cnAddress+" 经度:"+map.get("lng")+" 纬度:"+map.get("lat"));
}
}
/**
* 返回输入地址的经纬度坐标
* lng(经度),lat(纬度)
*/
//1,申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
public static final String AK= "VGqyTtpnqfNxkTkPBG5APrGO";
public static Map<String,String> getLatitude(String address){
try {
address = URLEncoder.encode(address, "UTF-8"); //将地址转换成utf-8的16进制
//2, 拼写发送http请求的url,注意需使用第一步申请的ak。
//3, 接收http请求返回的数据(支持json和xml格式)本次采用json形式
URL resjson = new URL("http://api.map.baidu.com/geocoder/v2/?address="
+ address +"&output=json&ak="+ AK);
BufferedReader in = new BufferedReader(
new InputStreamReader(resjson.openStream()));
String res;
StringBuilder sb = new StringBuilder("");
while((res = in.readLine())!=null){
sb.append(res.trim());
}
in.close();
String str = sb.toString();
//System.out.println("return json:"+str);
Map<String,String> map = null;
if(str!=null){
int lngStart = str.indexOf("lng\":");
int lngEnd = str.indexOf(",\"lat");
int latEnd = str.indexOf("},\"precise");
if(lngStart > 0 && lngEnd > 0 && latEnd > 0){
String lng = str.substring(lngStart+5, lngEnd);
String lat = str.substring(lngEnd+7, latEnd);
map = new HashMap<String,String>();
map.put("lng", lng);
map.put("lat", lat);
return map;
}
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

运行结果:

5.简单应用

期望实现功能:

input.txt存放中文地址
从input.txt中读取中文地址,获得经纬度
将中文地址以及经纬度输出到output.txt中
package addressToGeo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*; public class GetLatAndLngByBaidu { public static void main(String args[]){ long startTime=System.currentTimeMillis();
String fileSourcePath="F://Essex//AddressToGeo//source//input.txt";
String fileDestPath="F://Essex//AddressToGeo//source//output.txt";
readAddressWriteGeo(fileSourcePath,fileDestPath); }
/**
* 返回输入地址的经纬度坐标
* key lng(经度),lat(纬度)
*/
//1,申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
public static final String AK= "VGqyTtpnqfNxkTkPBG5APrGO";
public static Map<String,String> getLatitude(String address){
try {
address = URLEncoder.encode(address, "UTF-8"); //将地址转换成utf-8的16进制
//2, 拼写发送http请求的url,注意需使用第一步申请的ak。
//3, 接收http请求返回的数据(支持json和xml格式)本次采用json形式
URL resjson = new URL("http://api.map.baidu.com/geocoder/v2/?address="
+ address +"&output=json&ak="+ AK);
BufferedReader in = new BufferedReader(
new InputStreamReader(resjson.openStream()));
String res;
StringBuilder sb = new StringBuilder("");
while((res = in.readLine())!=null){
sb.append(res.trim());
}
in.close();
String str = sb.toString();
//System.out.println("return json:"+str);
Map<String,String> map = null;
if(str!=null){
int lngStart = str.indexOf("lng\":");
int lngEnd = str.indexOf(",\"lat");
int latEnd = str.indexOf("},\"precise");
if(lngStart > 0 && lngEnd > 0 && latEnd > 0){
String lng = str.substring(lngStart+5, lngEnd);
String lat = str.substring(lngEnd+7, latEnd);
map = new HashMap<String,String>();
map.put("lng", lng);
map.put("lat", lat);
return map;
}
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
*void readAddressWriteGeo(String sourceFilePath,String destFilePath) 函数
*功能:从sourceFilePath下读取中文地址,获取经纬度,存放在destFilePath中
* */
public static void readAddressWriteGeo(String sourceFilePath,String destFilePath)
{
long startTime=System.currentTimeMillis();
try
{
System.out.println("读取中文地址...");
String encoding="Unicode";
File fileSource=new File(sourceFilePath);//获得输入句柄
FileInputStream fis=new FileInputStream(fileSource);//创建字节流输入对象
InputStreamReader inStream=new InputStreamReader(fis,encoding);//将字节流转换为字符流,编码格式为Unicode,创建字节流输入对象
BufferedReader input=new BufferedReader(inStream); String outputFilePath=createFile(destFilePath);
File fileDest=new File(outputFilePath);//获得输出文件句柄
FileOutputStream fos=new FileOutputStream(destFilePath);//创建字节流输出对象
OutputStreamWriter outStream=new OutputStreamWriter(fos,encoding);//将字节流转换为字符流,编码格式为Unicode,创建字节流输出对象
BufferedWriter output=new BufferedWriter(outStream); String cnAddress=null;
cnAddress=input.readLine();
System.out.println("通过百度api获取经纬度...");
int count=0;
while(cnAddress!=null)
{
//System.out.println(cnAddress);
Map<String,String> map = GetLatAndLngByBaidu.getLatitude(cnAddress);
if(null != map){
//System.out.println("经度:"+map.get("lng"));
//System.out.println("纬度:"+map.get("lat"));
output.write(map.get("lng")+" "+map.get("lat")+" "+cnAddress+"\r\n");
}
cnAddress=input.readLine();
count++;
}
input.close();
output.close(); System.out.println("获取:"+count+"条经纬度信息");
long endTime=System.currentTimeMillis();
System.out.println("花费时间: "+(endTime-startTime)/1000+"s");
System.out.println("经纬度获取成功!");
}
catch(IOException e)
{
e.printStackTrace();
}
}
//创建新的output.txt文档
public static String createFile(String filePath)
{
File f=new File(filePath);//构造一个路径的句柄
if(f.exists())//如果文件存在则删除,不存在则生成
{
f.delete();
}
else
{
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return f.getPath();
} }

运行测试结果:

6.改进

上面的解决方案使用单线程,数据量小的情况下还可以勉强使用。但是当数据量巨大时,耗时就非常的长(测试使用15000条地址数据差不多用了1小时)。考虑到耗费的时间主要花费在获取经纬度时服务器的响应上,因此考虑使用多线程。

从input.txt读入,然后将地址信息切分为多个数组,为每一个数组开一个线程,转换后统一输出到output.txt

实现代码:

package addressToGeo;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map; class MyThread extends Thread{
private String[] GpsAdd;
private static String AK = "NXlvvuBhTW1Bd7PaatQvyceV";
private String name = "";
private String[] Addmat = {" "};
private int MatLen=0;
public MyThread(String Name, String[] AddMat){
this.name=Name;
this.Addmat = AddMat;
}
public MyThread(){
}
public String[] getGpsAdd(){
return GpsAdd;
}
public void run(){
MatLen = Addmat.length;
GpsAdd = new String[MatLen];
for(int i=0;i<MatLen;i++){
Map<String,String> map = getLatitude(Addmat[i]);
System.out.println(this.name +": " + map.get("lng") + " " + map.get("lat")+ " " + Addmat[i] );
GpsAdd[i] = map.get("lng") + " " + map.get("lat")+ " " + Addmat[i] +"\n";
}
} public static Map<String,String> getLatitude(String address){ Map<String,String> map = new HashMap<String,String>();
try {
address = URLEncoder.encode(address, "UTF-8");
URL resjson = new URL("http://api.map.baidu.com/geocoder/v2/?address="
+ address +"&output=json&ak="+ AK);
URLConnection uc=resjson.openConnection();
uc.setConnectTimeout(1000*100);
uc.setReadTimeout(1000*100);
BufferedReader in = new BufferedReader(
new InputStreamReader(uc.getInputStream())); String res;
StringBuilder sb = new StringBuilder("");
while((res = in.readLine())!=null){
sb.append(res.trim());
}
in.close();
String str = sb.toString(); if(str!=null){
int lngStart = str.indexOf("lng\":");
int lngEnd = str.indexOf(",\"lat");
int latEnd = str.indexOf("},\"precise");
if(lngStart > 0 && lngEnd > 0 && latEnd > 0){
String lng = str.substring(lngStart+5, lngEnd);
String lat = str.substring(lngEnd+7, latEnd); map.put("lng", lng);
map.put("lat", lat); }
}
}catch (Exception e) {
e.printStackTrace();
}
return map;
}
public static String createFile(String filePath)
{
File f = new File(filePath);
if(f.exists()) {
f.delete();
}
else
{
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return f.getPath();
}
}
package addressToGeo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*; public class GetLatAndLngByBaidu { private static int NumOfThread = 100;
static String fileSourcePath="F://Essex//AddressToGeoAll//source//input.txt";
static String fileDestPath="F://Essex//AddressToGeoAll//source//output.txt"; public static void main(String args[]) throws InterruptedException, IOException{
long startTime=System.currentTimeMillis();
threadStart(startTime);
}
public static void threadStart(long startTime) throws InterruptedException, IOException
{
System.out.println("start...");
String cnAdd ="";
int cnLen = 0;
cnAdd = readAdd(fileSourcePath);
String[] AddStr = cnAdd.split(",");
cnLen = AddStr.length;
System.out.println("get "+cnLen+" chinese address successful...");
System.out.println("to get longitude and latitude ...");
int MatLen = cnLen/NumOfThread;
String [][] sp=new String[NumOfThread][MatLen];
MyThread [] mt=new MyThread[NumOfThread];
for(int j=0;j<NumOfThread;j++)
{
sp[j]=new String[MatLen];
for(int i=0;i<MatLen;i++)
{
sp[j][i]=AddStr[i+j*MatLen];
}
mt[j]=new MyThread("线程"+j,sp[j]);
mt[j].start();
} for(int j=0;j<NumOfThread;j++)
{
mt[j].join();
}
String[] result;
FileWriter letter = new FileWriter(fileDestPath); for(int j=0;j<NumOfThread;j++)
{
result = mt[j].getGpsAdd();
writeFile(result,letter,MatLen);
} //处理结尾由于不能被100整数引起多余的几个数据
if(NumOfThread*MatLen <= cnLen-1){
String[] LastMat = new String[cnLen-NumOfThread*MatLen];
for(int i =0;i<cnLen-NumOfThread*MatLen;i++){
LastMat[i] = AddStr[NumOfThread*MatLen+i];
}
MyThread LastThread = new MyThread("线程last",LastMat);
LastThread.start();
LastThread.join();
result = LastThread.getGpsAdd();
writeFile(result, letter, cnLen-NumOfThread*MatLen);
}
letter.close();
getExcuteTime(startTime);
} //1,申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
public static final String AK= "NXlvvuBhTW1Bd7PaatQvyceV";
public static String readAdd(String sourceFilePath){
try{
String encoding="Unicode";
File fileSource=new File(sourceFilePath);//获得输入句柄
FileInputStream fis=new FileInputStream(fileSource);//创建字节流输入对象
InputStreamReader inStream=new InputStreamReader(fis,encoding);//将字节流转换为字符流,编码格式为Unicode,创建字节流输入对象
BufferedReader input=new BufferedReader(inStream); String cnAddress=null;
cnAddress=input.readLine();
StringBuilder sb = new StringBuilder("");
while(cnAddress!=null){
sb.append(cnAddress.trim());
sb.append(",");
cnAddress=input.readLine();
}
String sbStr = sb.toString();
// System.out.println(sb.toString()); //输出所有地址
input.close();
return sbStr;
} catch (IOException e){
e.printStackTrace();
}
return null;
}
public static void getExcuteTime(long startTime)
{
long endTime=System.currentTimeMillis();
long time=endTime-startTime;
System.out.println("take time: "+time/1000+" second");
System.out.println("about "+time/1000/60+" minute");
}
public static void writeFile(String[] result, FileWriter writer, int MatLen) throws IOException{
for(int i = 0;i<MatLen;i++){
writer.write(result[i]);;
}
}
}
7.不足

1,网速不好的情况下,开100个线程会出现 java.net.SocketTimeoutException: connect timed out错误。

虽然使用了uc.setConnectTimeout(10000);   uc.setReadTimeout(10000); 但是没有起到效果。(求改进)

2,所有的数据都会放在内存上,当数据量到达千万级别时候,会内存不足。(求改进)

8.引用

http://developer.baidu.com/map/webservice-geocoding.htm

http://www.cnblogs.com/gzggyy/archive/2013/06/21/3148610.html

http://lavasoft.blog.51cto.com/62575/99150

http://www.360doc.com/content/13/0422/09/3776353_280044198.shtml

												

通过地址获得经纬度(百度Geocoding API)的更多相关文章

  1. 【地图功能开发系列:二】根据地址名称通过百度地图API查询出坐标

    根据地址名称通过百度地图API查询出坐标 百度地图ApiUrl string url = "http://api.map.baidu.com/geocoder?address={0}& ...

  2. 百度地图地址解析(百度Geocoding API)

    1.什么是Geocoding? Geocoding API 是一类简单的HTTP接口,用于提供从地址到经纬度坐标或者从经纬度坐标到地址的转换服务,用户可以使用C# .C++.Java等开发语言发送HT ...

  3. 利用百度API(js),怎样通过地址获取经纬度

    根据经纬度找到具体地址:http://api.map.baidu.com/geocoder?location=纬度,经度&output=输出格式类型&key=用户密钥如:http:// ...

  4. 百度地图API地点搜索-获取经纬度

    分享一下地图上的地点搜索和鼠标点击获取地点经纬度,这些都是地图比较基本和实用的代码,其中还包括了根据用户IP进行地图的显示.改变地图上的鼠标样式.启用滚轮缩放等,算是半入门吧,其他的一些可以自己参考百 ...

  5. 百度地图API开发指南

    简介什么是百度地图API? 百度地图API是一套由JavaScript语言编写的应用程序接口,它能够帮助您在网站中构建功能丰富.交互性强的地图应用.百度地图API包含了构建地图基本功能的各种接口,提供 ...

  6. (转)百度Map API

    转自  http://blog.sina.com.cn/s/blog_6079f38301013sb3.html 一.与地图操作相关的接口哦! (这些接口的开启都是写在执行成功的回调函数那里) map ...

  7. php用百度地图API进行IP定位和GPS定位

    <?php /** * 根据地理坐标获取国家.省份.城市,及周边数据类(利用百度Geocoding API实现) * 百度密钥获取方法:http://lbsyun.baidu.com/apico ...

  8. 谷歌、腾讯、百度相应API批量获取地理位置坐标信息及其优缺点

    目录: 申请ak 批量获取地理位置 目的:通过给定的地理位置名称(如:北京市海淀区上地十街十号),获取经纬度信息. 1.申请ak 以百度Geocoding API为例:http://lbsyun.ba ...

  9. php用百度地图API进行逆地址解析

    <?php /** * 根据地理坐标获取国家.省份.城市,及周边数据类(利用百度Geocoding API实现) * 百度密钥获取方法:http://lbsyun.baidu.com/apico ...

随机推荐

  1. 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

    'utf-8' codec can't decode byte 0xff in position 0: invalid start byte 觉得有用的话,欢迎一起讨论相互学习~Follow Me 今 ...

  2. java之Servlet监听器Listener

    常用应用场景:单点登录.统计在线人数 一.简介 (一)概述 1.Listener 用于监听 java web程序中的事件,例如创建.修改.删除Session.request.context等,并触发响 ...

  3. ABP官方文档翻译 3.3 仓储

     仓储 默认仓储 自定义仓储 自定义仓储接口 自定义仓储实现 基础仓储方法管理数据库连接 查询 获取单个实体 获取实体列表 关于IQueryable 自定义返回值 插入 更新 删除 其他 关于异步方法 ...

  4. 为Ghost博客扩展代码高亮、数学公式、页面统计、评论

    前几天捣鼓了一下博客首页,接下来再丰富一下博客页面的功能与内容.由于我所使用的Ghost博客专注于轻量简洁,因此标题中提到的功能在Ghost中默认均不支持.下面将逐个介绍一下如何为Ghost扩展这些功 ...

  5. 济南清北学堂游记 Day 6.

    还剩一天半我就该回去了. 说实话今天挺可惜的,有很多本来可以得到的分数评测时没有拿到.上午的第一题和第二题我都想出了正解,T3敲了一个暴力,虽然暴力写坏了.预计是可以拿210的但是实际上只有很少的分数 ...

  6. BZOJ 1025: [SCOI2009]游戏 [置换群 DP]

    传送门 题意:求$n$个数组成的排列变为升序有多少种不同的步数 步数就是循环长度的$lcm$..... 那么就是求$n$划分成一些数几种不同的$lcm$咯 然后我太弱了这种$DP$都想不出来.... ...

  7. POJ Ikki's Story IV - Panda's Trick [2-SAT]

    题意: 圆上n个点,m对点之间连边,连在园内或园外,所有边不相交是否可行 发现两对点连线都在内相交则都在外也相交,那么只有一个在内一个在外啦,转化为$2-SAT$问题 #include <ios ...

  8. DNA序列局部比对(Smith–Waterman algorithm)

    生物信息原理作业第三弹:DNA序列局部比对,利用Smith–Waterman算法,python3.6代码实现. 实例以及原理均来自https://en.wikipedia.org/wiki/Smith ...

  9. javascript 一些特殊的字符运算

    1.什么是 --> ? 这两个分开是很简单的两个运算符,比如--,一般表示自减,var i = 5;while(i){console.log(i--);},会打印出5,4,3,2,1: > ...

  10. [Python Study Notes]实现对键盘控制与监控

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...