在supermap客户端开发中要实现正向地理编码和反向地理编码,就需要发布地址匹配服务。超图自带的地址字典库在一定程度上能满足我们的需求,但是很多业务情况下,我们需要根据自己的海量数据(我应用的情景是需要给几十万个poi点制作地址词典)定制地址字典。
关于地址匹配是什么,数据字典是什么,我这里不做详细介绍了,不明白的可以看超图的文档,写的非常仔细了。下面提供跳转链接:
地址匹配:
离线文档下载链接:
http://support.supermap.com.cn/DataWarehouse/WebDocHelp/SuperMap_iObjects_Java_Help.zip
通过阅读文档,我们可以知道想要制作地址词典,需要使用supermap iobects java,同时需要有对应的许可才可以搭建好环境。
supermap iobects java下载地址:
http://support.supermap.com.cn/DownloadCenter/ProductPlatform.aspx
下载好后解压到一个目录下即可
其中我们会用到的是Bin目录下的资源。
现在还需要在你的许可中有iobject java的许可模块。我相信有心看这篇文章的人自己的电脑里都有supermap idesktop以及supermap 许可中心,如果你一开始申请许可的时候全勾选了,那你可以跳过此步,如果没有,需要为你的电脑重新申请带iobect java许可模块的试用许可。
试用许可申请地址:
https://sso.supermap.com/login?service=https://www.supermapol.com/web/mycontent/cloud/security/shiro-cas
生成*.lic9d或其他形式的许可文件后,去本机的许可中心更新许可。
更新完之后,iobject java模块才可以在本机使用。我们还需明白一个东西,supermap iobject java
不是一个单独的软件,只是一些资源包罢了。我们还需要一个java开发工具,我们就使用超图文档里推荐的eclipse就可以了,熟悉其他开发工具的也可以使用其他的。
eclipse下载地址:
https://www.eclipse.org/downloads/download.php?file=/oomph/epp/2018-12/R/eclipse-inst-win64.exe
注意选择下载镜像时选择距离自己最近的位置,这样下载速度快
此处我选择的是中国科学技术大学的镜像。
下载好后,安装eclipse以及没有配置jdk环境变量的部分请百度其他博客哈,说多了就跑偏了。
好的,我们已经安装好了eclipse。
新建一个java工程
点击下一步,选择添加内部jar包。
导航到SuperMap iobject java Bin目录。
选中所有的jar包(有时候我们不知道会用到哪个jar包,反正选中所有的就对惹)
点击完成。在工程的src目录下新建包 package1
在包上右键新建java类。
如下:
返回我们的需求,我们是要制作地址字典。文档中有这么一部分:
其中的意思是通过增加单个词生成地址词典。但是上面也没有给出示例代码。经过我的阅读,我写了一套示例代码如下:
package package1;
import com.supermap.analyst.addressmatching.AddressDictionary;
public class heihei {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 新建地址字典类 指定地址字典文件的位置 这个文件需要提前建好(直接新建一个空的文本文档改后缀为.dct)
AddressDictionary address=new AddressDictionary("C:\\Users\\lenovo\\Desktop\\addressTrans\\gongsi.dct");
System.out.println(address.add("北京"));//加入数据字典 返回对字典索引值
System.out.println(address.add("西直门"));
System.out.println(address.add("西二旗"));
System.out.println(address.save());//返回值为true表示存储成功。
}
}
运行程序,控制台显示索引以及true后表示成功,查看对应位置的dct文件大小,不是0b则且用记事本打开有内容,即为成功。
(下面这个只是举例,和上文无关)
此时我们已经会用单个词制作地址字典了。那么如果我有十万个分词怎么办?
我们可能会想到制作一个包含十万个数据的数组去循环执行address.add(“西二旗”),但是这样的数组容易维护吗?
我们接着看文档的第二种方式:
说如果我们有一个分词的文本文件,就可以直接根据这个文件通过AddressDictionary类的静态方法textToDictionary(String textFile,String dictionaryFile)去直接生成。
问题是:这个存储分词的文本文件是何种形式的?json文件吗,xml吗,还是用逗号或空格分隔,或者用其他方式来存储?
这里我就不再绕圈子了,如果需要存储“北京”“西直门”“西二旗”这三个中文分词,所需要的txt文本格式如下:
根据文本文档生成地址字典代码如下:
package package1;
import com.supermap.analyst.addressmatching.AddressDictionary;
public class heihei {
public static void main(String[] args) {
// TODO Auto-generated method stub
//第一个参数为txt路径,第二个为生成的dct路径。
System.out.print(AddressDictionary.textToDictionary("C:\\Users\\lenovo\\Desktop\\addressTrans\\zonghe.txt","C:\\Users\\lenovo\\Desktop\\addressTrans\\zonghe.dct"));
}
}
运行程序,稍后如果在控制台输出true,则证明生成完成。
这是最简单的方式,代码量只有一行。
以上只是测试环境下我们走通了流程,真实的环境下,我要为某个有几十万条poi数据的要素图层的某列建立数据字典,我不能手动地一个一个向txt中加分词,那么我如何从要素图层中获得这一列几十万条数据的txt呢?
首先无论是超图还是arcgis,都是可以将要素类导出为csv文件的,我们得到了csv文件后,我们就算成功了一半。
拿到csv文件后,双击打开该文件,复制要作为分词的一列,创建一个新的csv文件,粘贴到里面,保存退出该新的csv文件。
用notepad++或其他记事本打开这个新的csv文件,就会发现已经规范好了,此时复制其中的所有内容,到一个新的txt文本中,然后更改编码方式为ansci编码,保存。
接下来我们就可以按照第二种方法生成地址字典了。
拓展:public static boolean AddressDictionary.textToDictionary(String textFile,String dictionaryFile)的源码模拟。
此方法是输入一个文本文件位置,一个生成地址字典的位置作为参数,来生成地址字典的。我们可以发现,文本文件是每行一个数据,其实我们就是在读取txt的每一行数据,去除其重复数据,不断执行address.add(“分词”)方法来实现的。
模拟源代码如下:
package package1;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import com.supermap.analyst.addressmatching.AddressDictionary;
import com.supermap.analyst.addressmatching.AddressMatchSetting;
import com.supermap.data.DatasetVector;
public class heihei {
/**
* @param list 要去除重复数据的集合
*
*/
public static void removeDuplicate(List list) {
for (int i = 0; i < list.size() - 1; i++) {
for (int j = list.size() - 1; j > i; j--) {
if (list.get(j).equals(list.get(i))) {
list.remove(j);
}
}
}
System.out.println(list);
}
/**
* @param txtPath 文本路径
* @return 存放数据的集合
* 读取txt到arrayList中
*/
public static List getNoDuplicationListFromText(String txtPath) {
//定义一个list去存放数据
List<String> arrayList = new ArrayList<>();
File file=new File(txtPath);
BufferedReader reader=null;
String temp=null;
int line=1;
try{
reader=new BufferedReader(new FileReader(file));
while((temp=reader.readLine())!=null){
//System.out.println("line"+line+":"+temp);
arrayList.add(temp);
line++;
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
if(reader!=null){
try{
reader.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
//去重
removeDuplicate(arrayList);
return arrayList;
}
/**
* @param textFile 分词文本文件路径
* @param dictionaryFile 地址字典路径
* 自己的文本生成地址字典方法。
*/
public static void mytextToDictionary(String textFile,String dictionaryFile) {
// 新建地址字典类 指定地址字典文件的位置
AddressDictionary address=new AddressDictionary(dictionaryFile);
//从文本数据取得集合
List<String> arrayList=getNoDuplicationListFromText(textFile);
for(String attribute : arrayList) {
System.out.println(attribute);
address.add(attribute);
System.out.println(address.add(attribute));//加入数据字典
}
System.out.println(address.save());//返回值为true表示存储成功。
}
public static void main(String[] args) {
//调用方法。
mytextToDictionary("C:\\Users\\lenovo\\Desktop\\addressTrans\\gongsi.txt","C:\\Users\\lenovo\\Desktop\\addressTrans\\gongsi.dct");
//超图的方法:
//System.out.print(AddressDictionary.textToDictionary("C:\\Users\\lenovo\\Desktop\\addressTrans\\zonghe.txt","C:\\Users\\lenovo\\Desktop\\addressTrans\\zonghe.dct"));
}
}
下期 地址匹配服务发布及其参数。