根据地址获取经纬度

来源:互联网 发布:战舰世界洛阳数据 编辑:程序博客网 时间:2024/05/01 07:20
package com.maputil;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;public class AddressLatLngUtil {private static final String REQUEST_ENCODE = "UTF-8";private static final String ADDRESS_KEY = "\"address\"";private static final String ADDRESS_COUNTRY_KEY = "\"CountryName\"";private static final String ADDRESS_REGION_KEY = "\"AdministrativeAreaName\"";private static final String ADDRESS_CITY_KEY = "\"LocalityName\"";private static final String ADDRESS_POINT_KEY = "\"coordinates\"";private static final String ADDRESS_SPLIT_STR = ":";private static final String LOCATION_SPLIT_STR = ",";public static final int MIN_ZOOM = 11;public static final int MAX_ZOOM = 18;private static final int DOWNNUM_FOR_PROXY = 8000;private static final int CONNECT_TIMEOUT = 30000; //30秒private static final int THREAD_SLEEP_MILLIS = 200;private static boolean flag = false;private static int downNum = 0;private static String proxyHost = "165.228.128.10";private static String proxyPort = "3128";private static String proxySet = "true";/** * 获取地址详细信息及经纬度信息 * @Title: getAddressLatLng  * @param address * @return Map<String,Point><地址, 经纬度> * @author:zhengxingmiao * @time: Nov 1, 2011 10:29:53 AM */public static Map<String, Point> getAddressLatLng(String address) {StringBuilder urlBuilder = new StringBuilder();urlBuilder.append("http://ditu.google.cn/maps/geo");urlBuilder.append("?output=json");urlBuilder.append("&oe=utf-8");urlBuilder.append("&q=").append(encodeURLForUTF8(address));urlBuilder.append("&key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA");urlBuilder.append("&mapclient=jsapi");urlBuilder.append("&hl=zh-CN");urlBuilder.append("&callback=_xdc_._1g4gm5mh3");//System.out.println(urlBuilder);HttpURLConnection httpConnection = null;try {//1构造HttpURLConnection连接URL url = new URL(urlBuilder.toString());URLConnection urlConnection = url.openConnection();httpConnection = (HttpURLConnection) urlConnection;httpConnection.setDoInput(true);httpConnection.setDoOutput(true);httpConnection.setConnectTimeout(CONNECT_TIMEOUT);httpConnection.connect();//2接收响应结果InputStream inStream = httpConnection.getInputStream();String htmlContent = getContentByStream(inStream, REQUEST_ENCODE);// 关闭流资源inStream.close();//3解析结果Map<String, Point> map = parseAddressLatLng(htmlContent);updateProxy();return map;} catch (Exception e) {e.printStackTrace();//System.out.println("===========获取经纬度信息异常!请求地址:" + address);return java.util.Collections.emptyMap();} finally {//关闭连接if (null != httpConnection) {httpConnection.disconnect();}}}/** * 地址信息转码 * @Title: encodeURLForUTF8  * @param str * @return String * @author:zhengxingmiao * @time: Nov 1, 2011 10:32:16 AM */private static String encodeURLForUTF8(String str) {try {str = java.net.URLEncoder.encode(str, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();System.out.println("字符串转码异常,字符串:" + str);}return str;}/** * 按照指定编码从流中读取信息 * @Title: getContentByStream  * @param inStream * @param encode * @return * @throws IOException String * @author:zhengxingmiao * @time: Nov 1, 2011 10:32:46 AM */private static String getContentByStream(InputStream inStream, String encode)throws IOException {if (null == inStream) {return null;}StringBuilder content = new StringBuilder();//采用指定编码格式读取流内容BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, encode));String message = null;while (null != (message = reader.readLine())) {content.append(message);content.append("\r\n");}//关闭读取器,释放资源reader.close();return (content.toString());}/** * 解析网页内容地址信息及经纬度信息 * @Title: parseAddressLatLng  * @param htmlContent * @return Map<String,Point><地址, 经纬度> * @author:zhengxingmiao * @time: Nov 1, 2011 10:33:59 AM */private static Map<String, Point> parseAddressLatLng(String htmlContent) {Map<String, Point> addr = new HashMap<String, Point>(1);if (isNullOrEmpty(htmlContent)) {return addr;}String[] contents = htmlContent.split("\r\n");String[] ss = null;String address = null;String country = null;String region = null;String city = null;Point point = null;for (String line : contents) {if (isNullOrEmpty(line)) {continue;}line = line.trim();if (line.contains(ADDRESS_POINT_KEY)) {//coordinates": [ 113.9465830, 22.5309650, 0 ]ss = line.split(ADDRESS_SPLIT_STR);if (null != ss && ss.length > 1) {String pointStr = getMiddleStr(ss[1], "[", "]");String[] pss = pointStr.split(",");if (null != pss && pss.length > 1) {double defaultValue = 0D;point = new Point(isNullOrEmpty(pss[0]) ? defaultValue: Double.parseDouble(pss[0].trim()),isNullOrEmpty(pss[1]) ? defaultValue : Double.parseDouble(pss[1].trim()));}}} else if (line.contains(ADDRESS_KEY)) {address = getValue(line, ADDRESS_KEY);} else if (line.contains(ADDRESS_COUNTRY_KEY)) {country = getValue(line, ADDRESS_COUNTRY_KEY);} else if (line.contains(ADDRESS_REGION_KEY)) {region = getValue(line, ADDRESS_REGION_KEY);} else if (line.contains(ADDRESS_CITY_KEY)) {city = getValue(line, ADDRESS_CITY_KEY);}//默认取第一个地址信息if (false == isNullOrEmpty(address) && null != point) {point.setCountry(country);point.setRegion(region);point.setCity(city);break;}} //end-for-contents// 如果地址不为空if (false == isNullOrEmpty(address)) {addr.put(address, point);}return addr;}/** * 根据地址信息获取经纬度 * @Title: getAddressLatLng  * @param addressList地址集合 * @return List<Map<String,Point>><Map<地址, 经纬度对象>> * @author:zhengxingmiao * @time: Nov 1, 2011 10:35:23 AM */public static List<Map<String, Point>> getAddressLatLng(List<String> addressList) {List<Map<String, Point>> list = new ArrayList<Map<String, Point>>();if (null == addressList || addressList.isEmpty()) {return list;}for (String address : addressList) {try {//休息一下Thread.sleep(THREAD_SLEEP_MILLIS);} catch (InterruptedException e) {e.printStackTrace();}Map<String, Point> addrMap = getAddressLatLng(address);if (false == addrMap.isEmpty()) {list.add(addrMap);} else {System.out.println("===========获取经纬度信息为空!请求地址:" + address);}}return list;}/** * 获取中间字符串内容 * @Title: getMiddleStr  * @param content * @param beginStr * @param endStr * @return String * @author:zhengxingmiao * @time: Nov 1, 2011 10:36:22 AM */private static String getMiddleStr(String content, String beginStr,String endStr) {String str = "";if (isNullOrEmpty(content)) {return str;}content = content.trim();int bIndex = content.indexOf(beginStr);int eIndex = -1;if (null != beginStr && beginStr.equals(endStr)) {int index = content.substring(bIndex + beginStr.length()).indexOf(endStr);eIndex = content.substring(0, bIndex + beginStr.length()).length()+ index;} else if (null != endStr && false == endStr.equals(beginStr)) {eIndex = content.indexOf(endStr);}if (-1 != bIndex && -1 != eIndex) {str = content.substring(bIndex + beginStr.length(), eIndex);}return str;}private static final String PROXY_HOST_KEY = "http.proxyHost";private static final String PROXY_PORT_KEY = "http.proxyPort";private static final String PROXY_SET_KEY = "http.proxySet";//切换代理private static synchronized void updateProxy() {downNum++;if (downNum % DOWNNUM_FOR_PROXY == 0) {if (flag) {clearProxy();flag = false;} else {setProxy();flag = true;}}}private static void setProxy() {System.setProperty(PROXY_HOST_KEY, proxyHost);System.setProperty(PROXY_PORT_KEY, proxyPort);System.setProperty(PROXY_SET_KEY, proxySet);System.out.println("setProxy=====" + proxyHost + ":" + proxyPort);}private static void clearProxy() {System.clearProperty(PROXY_HOST_KEY);System.clearProperty(PROXY_PORT_KEY);System.clearProperty(PROXY_SET_KEY);System.out.println("clearProxy=====");}/** * 获取偏移后的经纬度(Google中国地图偏移接口) 中国地图和卫星图都存在偏移量,这个是由中国规划局确定的, * google的地图服务,以ditu.gogle开头的都没有偏差,以maps.google开头的服务就有偏差 * @Title: getOffsetLatLng  * @param zoom偏移级别(从11级到18级,18级最精确) * @param sourcePoint经纬度对象 * @return Point * @author:zhengxingmiao * @time: Nov 1, 2011 10:37:54 AM */public static Point getOffsetLatLng(int zoom, Point sourcePoint) {if (null == sourcePoint) {return null;}StringBuilder urlBuilder = new StringBuilder();urlBuilder.append("http://ditu.google.cn/maps/vp");urlBuilder.append("?spn=0.0,0.0");urlBuilder.append("&z=").append(zoom);urlBuilder.append("&vp=");urlBuilder.append(sourcePoint.getLatitude());// 纬度urlBuilder.append(",");urlBuilder.append(sourcePoint.getLongitude());// 经度HttpURLConnection httpConnection = null;try {//构造HttpURLConnection连接URL url = new URL(urlBuilder.toString());URLConnection urlConnection = url.openConnection();httpConnection = (HttpURLConnection) urlConnection;httpConnection.setDoInput(true);httpConnection.setDoOutput(true);httpConnection.setConnectTimeout(CONNECT_TIMEOUT);httpConnection.connect();//接收响应结果InputStream inStream = httpConnection.getInputStream();String htmlContent = getContentByStream(inStream, REQUEST_ENCODE);// 关闭流资源inStream.close();//解析结果String offset = parseOffsetFromZoom(zoom, htmlContent);// 如果没有偏移值,则返回原经纬度对象if (isNullOrEmpty(offset)) {return sourcePoint;}Point targetPoint = getOffsetPoint(offset, zoom, sourcePoint);updateProxy();//System.out.println("sourcePoint: " + sourcePoint);//System.out.println("targetPoint: " + targetPoint);return targetPoint;} catch (Exception e) {e.printStackTrace();System.out.println("===========获取偏移经纬度信息异常!zoom = " + zoom+ ", sourcePoint = " + sourcePoint);} finally {// 关闭连接if (null != httpConnection) {httpConnection.disconnect();}}return null;}/** * 获取对应级别像素偏移量 * @Title: parseOffsetFromZoom  * @param zoom * @param htmlContent * @return String * @author:zhengxingmiao * @time: Nov 1, 2011 10:39:52 AM */private static String parseOffsetFromZoom(int zoom, String htmlContent) {String offset = null;if (isNullOrEmpty(htmlContent) || zoom > MAX_ZOOM || zoom < MIN_ZOOM) {return offset;}/* * 下面分别表示经纬度、级别、偏移像素数量【级别从11级到18级,共8组数字】 * 前一组数字精确的等于后一组数字除二,我们为了得到最精确的偏移,故选择第18级的偏移量1193,-270, * 1193为x方向上精度的偏移像素,-270为y方向上维度偏移像素 *  * window.GTileShiftUpdateOffset && window.GTileShiftUpdateOffset( * 39.111195, 117.148067, 18, [9, -2, 18, -4, 37, -8, 74, -16, 149, -33, * 298, -67, 596, -135, 1193, -270]); */int beginIndex = htmlContent.lastIndexOf("[");int endIndex = htmlContent.lastIndexOf("]");if (beginIndex > 0 && endIndex > 0) {// 获取各级别像素偏移量内容String content = htmlContent.substring(beginIndex + 1, endIndex);offset = getOffsetByZoom(zoom, content);}return offset;}/** * 获取zoom级别的像素偏移量 * @Title: getOffsetByZoom  * @param zoom * @param content * @return String * @author:zhengxingmiao * @time: Nov 1, 2011 10:40:21 AM */private static String getOffsetByZoom(int zoom, String content) {String[] ss = content.split(",");int index = ((zoom - 10) << 1) - 2;if (null == ss || ss.length < (index + 1)) {return null;}return (ss[index].trim() + "," + ss[index + 1].trim());}/** * 获取校正后的经纬度 * @Title: getOffsetPoint  * @param offset * @param zoom * @param point * @return Point * @author:zhengxingmiao * @time: Nov 1, 2011 10:40:28 AM */private static Point getOffsetPoint(String offset, int zoom, Point point) {String[] ss = offset.split(",");int offsetX = Integer.parseInt(ss[0]);int offsetY = Integer.parseInt(ss[1]);double lngPixel = (Math.round(lngToPixel(point.getLongitude(), zoom)) - offsetX);double latPixel = (Math.round(latToPixel(point.getLatitude(), zoom)) - offsetY);return new Point(pixelToLng(lngPixel, zoom), pixelToLat(latPixel, zoom));}/* * sinLatitude = sin(latitude * pi/180) *  * pixelX = ((longitude + 180) / 360) * 256 * 2level *  * pixelY = (0.5 – log((1 + sinLatitude) / (1 – sinLatitude)) / (4 * pi)) * * 256 * 2level *//** * 经度到像素X值 * @Title: lngToPixel  * @param lng * @param zoom * @return double * @author:zhengxingmiao * @time: Nov 1, 2011 10:41:18 AM */private static double lngToPixel(double lng, int zoom) {return (lng + 180) * (256L << zoom) / 360;}/** * 纬度到像素Y * @Title: latToPixel  * @param lat * @param zoom * @return double * @author:zhengxingmiao * @time: Nov 1, 2011 10:41:07 AM */private static double latToPixel(double lat, int zoom) {double siny = Math.sin(lat * Math.PI / 180);double y = Math.log((1 + siny) / (1 - siny));return (256L << zoom) * (0.5 - y / (4 * Math.PI));}/** * 像素X到经度 * @Title: pixelToLng  * @param pixelX * @param zoom * @return double * @author:zhengxingmiao * @time: Nov 1, 2011 10:41:33 AM */private static double pixelToLng(double pixelX, int zoom) {return pixelX * 360 / (256L << zoom) - 180;}/** * 像素Y到纬度 * @Title: pixelToLat  * @param pixelY * @param zoom * @return double * @author:zhengxingmiao * @time: Nov 1, 2011 10:41:38 AM */private static double pixelToLat(double pixelY, int zoom) {double y = 4 * Math.PI * (0.5 - pixelY / (256L << zoom));double z = Math.pow(Math.E, y);double siny = (z - 1) / (z + 1);return Math.asin(siny) * 180 / Math.PI;}/** * 获取数值 * @Title: getValue  * @param content * @param key * @return String * @author:zhengxingmiao * @time: Nov 1, 2011 10:42:48 AM */private static String getValue(String content, String key) {if (false == isNullOrEmpty(content) && false == isNullOrEmpty(key)) {String[] ss = content.split("\r\n");for (String line : ss) {if (isNullOrEmpty(line)) {continue;}line = line.replace("{", "").replace("}", "").replace("[", "").replace("]", "").trim();String[] sss = line.split(LOCATION_SPLIT_STR);for (String str : sss) {if (isNullOrEmpty(str) || false == str.contains(key)) {continue;}String[] sub = str.split(ADDRESS_SPLIT_STR);for (int i = 0; i < sub.length; i++) {if (isNullOrEmpty(sub[i])) {continue;}sub[i] = sub[i].trim();}List<String> subList = java.util.Arrays.asList(sub);int subIndex = subList.indexOf(key);if (-1 != subIndex && subList.size() > (subIndex + 1)) {String value = subList.get(subIndex + 1);return (value.replace("\"", "").trim());}}// end-for-sss}// end-for-ss}return null;}/** * 判断字符串是否为空 * @Title: isNullOrEmpty  * @param str * @return boolean * @author:zhengxingmiao * @time: Nov 1, 2011 10:43:11 AM */public static boolean isNullOrEmpty(String str) {if (null == str || "".equals(str)) {return true;}return false;}/** * 经纬度坐标信息 */public static class Point {/** * 经度 */private double longitude;/** * 纬度 */private double latitude;/** * 精确度 */private double precision;/** * 国家 */private String country;/** * 省份 */private String region;/** * 城市 */private String city;/** * <p>Title: </p>  * <p>Description: </p>  * @param longitude经度 * @param latitude纬度 */public Point(double longitude, double latitude) {this.longitude = longitude;this.latitude = latitude;}public double getLongitude() {return longitude;}public void setLongitude(double longitude) {this.longitude = longitude;}public double getLatitude() {return latitude;}public void setLatitude(double latitude) {this.latitude = latitude;}public double getPrecision() {return precision;}public void setPrecision(double precision) {this.precision = precision;}public String toString() {StringBuilder content = new StringBuilder();content.append(getClass().getName());content.append("[ latitude=");content.append(this.latitude);content.append(", longitude=");content.append(this.longitude);if (this.precision != 0.0) {content.append(", precision=");content.append(this.precision);}if (false == isNullOrEmpty(this.country)) {content.append(", country=");content.append(this.country);}if (false == isNullOrEmpty(this.region)) {content.append(", region=");content.append(this.region);}if (false == isNullOrEmpty(this.city)) {content.append(", city=");content.append(this.city);}content.append(" ]");return (content.toString());}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getRegion() {return region;}public void setRegion(String region) {this.region = region;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}}public static String getProxyHost() {return proxyHost;}public static void setProxyHost(String proxyHost) {AddressLatLngUtil.proxyHost = proxyHost;}public static String getProxyPort() {return proxyPort;}public static void setProxyPort(String proxyPort) {AddressLatLngUtil.proxyPort = proxyPort;}/** * 测试 * @param args */public static void main(String[] args) {List<String> addrList = new ArrayList<String>();addrList.add("河北省石家庄市");List<Map<String, Point>> list = getAddressLatLng(addrList);for (Map<String, Point> map : list) {for (Entry<String, Point> entry : map.entrySet()) {//获取偏移坐标Point offsetPoint = getOffsetLatLng(MAX_ZOOM, entry.getValue());System.out.println("纬度:" + offsetPoint.longitude);System.out.println("经度:" + offsetPoint.latitude);}}//System.out.println("finished!");}}

原创粉丝点击