前言
由于是第一次接触swing和geotools,而且是奔着完成任务目标去接触的,所以了解得比较片面。
Javaswing简介:https://www.runoob.com/w3cnote/java-swing-demo-intro.html
Geotools简介:https://blog.csdn.net/qq_21225505/article/details/86181817
功能说明
- 将制定目录下的shp文件转换成geojson格式的文件,后缀可以自定义,可以是.txt、.json、.geojson等。
- 本项目是要求在转换过程中,需要指定name和describe两个字段作为转换后的字段,而这两个字段对应SHP文件里的字段需要人为选择映射。
- 代码中只对点和线的SHP文件转换做了判断处理。
1.新建maven工程
- 建项目过程此处省略。。。
2.pom配置
- 为了这个geotools的jar我真是抓破了头,maven库里找不到,需要另外配库。
<!-- 需要另外配置geotools工具包的下载地址 -->
<repositories>
<repository>
<id>osgeo</id>
<name>Open Source Geospatial Foundation Repository</name>
<url>http://download.osgeo.org/webdav/geotools/</url>
</repository>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>opengeo</id>
<name>OpenGeo Maven Repository</name>
<url>http://repo.opengeo.org</url>
</repository>
</repositories>
<!-- 工具包引入 -->
<dependencies>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>18.4</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>18.4</version>
</dependency>
</dependencies>
3.shp文件转geojson文件功能实现
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.geojson.feature.FeatureJSON;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
public class ShapeFileServer {
/*public static void main(String[] args) {
ShapeFileServer sfs = new ShapeFileServer();
sfs.reaferShp("D:/ShapeFile/states/states.shp");
//sfs.reaferShp("D:/ShapeFile/Data/USA/states.shp");
}*/
/**
* 获取元素的名称
* @param shpPath 文件路径
* @return 元素名称的集合
*/
public String[] getFeatureName(String shpPath){
List<String> list = new ArrayList<>();
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
try {
ShapefileDataStore sds = (ShapefileDataStore)dataStoreFactory.createDataStore(new File(shpPath).toURI().toURL());
sds.setCharset(Charset.forName("utf-8"));
SimpleFeatureSource featureSource = sds.getFeatureSource();
SimpleFeatureCollection simpleFeatureCollection = featureSource.getFeatures();
SimpleFeatureIterator itertor = simpleFeatureCollection.features();
//SimpleFeatureIterator itertor = featureSource.getFeatures().features();
while(itertor.hasNext()) {
SimpleFeature feature = itertor.next();
Iterator<Property> iterator = feature.getProperties().iterator();
if(list.size()==0) {
while(iterator.hasNext()) {
Property pro = iterator.next();
list.add(pro.getName().toString());
}
}
}
itertor.close();
} catch (Exception e) {
e.printStackTrace();
}
String[] str = new String[list.size()+1];
str[0] = "请选择";
for (int i = 0; i < list.size(); i++) {
str[i+1] = list.get(i);
}
return str;
}
/**
* 获取指定字段的所有不重复的值
* @param shpPath 文件路径
* @param name 指定字段
* @return 指定字段的值数组
*/
public String[] getValue(String shpPath , String name){
List<String> list = new ArrayList<>();
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
try {
ShapefileDataStore sds = (ShapefileDataStore)dataStoreFactory.createDataStore(new File(shpPath).toURI().toURL());
sds.setCharset(Charset.forName("utf-8"));
SimpleFeatureSource featureSource = sds.getFeatureSource();
SimpleFeatureCollection simpleFeatureCollection = featureSource.getFeatures();
SimpleFeatureIterator itertor = simpleFeatureCollection.features();
//SimpleFeatureIterator itertor = featureSource.getFeatures().features();
while(itertor.hasNext()) {
SimpleFeature feature = itertor.next();
Iterator<Property> iterator = feature.getProperties().iterator();
while(iterator.hasNext()) {
Property pro = iterator.next();
if(name.equals(pro.getName().toString())) {
if(!list.contains(pro.getValue().toString()) && !"".equals(pro.getValue().toString())) {
list.add(pro.getValue().toString());
}
}
}
}
itertor.close();
} catch (Exception e) {
e.printStackTrace();
}
String[] str = new String[list.size()+1];
str[0] = "请选择";
for (int i = 0; i < list.size(); i++) {
str[i+1] = list.get(i);
}
return str;
}
/**
* 读SHP文件,
* @param shpPath shp文件路径
* @return List<Map<String ,String>>(feature集合)
*/
public List<Map<String ,String>> reaferShp(String shpPath){
List<Map<String ,String>> list = new ArrayList<>();
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
try {
ShapefileDataStore sds = (ShapefileDataStore)dataStoreFactory.createDataStore(new File(shpPath).toURI().toURL());
sds.setCharset(Charset.forName("utf-8"));
SimpleFeatureSource featureSource = sds.getFeatureSource();
SimpleFeatureIterator itertor = featureSource.getFeatures().features();
while(itertor.hasNext()) {
Map<String ,String> map = new HashMap<>();
SimpleFeature feature = itertor.next();
Iterator<Property> iterator = feature.getProperties().iterator();
while(iterator.hasNext()) {
Property pro = iterator.next();
map.put(pro.getName().toString(), pro.getValue().toString());
}
list.add(map);
}
itertor.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 将geojson格式字符串保存进文件中
* @param content geojson格式字符串
* @throws IOException
*/
public void writeToGeojson(List<Map<String ,String>> list , String geoJsonPath) throws IOException {
FileWriter fileWriter=new FileWriter(geoJsonPath,true);//".json"
fileWriter.append("{\"type\":\"FeatureCollection\",\"features\":[");
for (int i = 0; i < list.size(); i++) {
Map<String,String> item = list.get(i);
fileWriter.append("{\"type\":\"Feature\",\"properties\":{");
String properties = "";
for (String key : item.keySet()) {
if(!"the_geom".equals(key)) {
properties+="\""+key+"\":\""+item.get(key)+"\",";
}
}
fileWriter.append(properties.subSequence(0, properties.length()-1));
fileWriter.append("},");
Map<String,String> map = parseCoordinate(list.get(i).get("the_geom"));
String geometryType = map.get("type");
fileWriter.append("\"geometry\":{\"type\":\""+geometryType+"\",\"coordinates\":");
String coordinate = map.get("value");
fileWriter.append(coordinate);
if(i==list.size()-1) {
fileWriter.append("}}");
}else {
fileWriter.append("}},");
}
fileWriter.flush();
}
fileWriter.append("]}");
fileWriter.flush();
fileWriter.close();
}
/**
* 按要求转换SHP文件成geojson格式--映射name、describe
* @param list 结果集
* @param mapping 映射name和describe
* @param geoJsonPath 转换后文件的保存路径
* @throws IOException
*/
public void appendToFile(List<Map<String ,String>> list ,Map<String ,String> mapping, String geoJsonPath) throws IOException{
//所选的条件名及选定的值
String conditionName = mapping.get("conditionName");
String conditionValue = mapping.get("conditionValue");
//放入需要写入的内容
List<Map<String ,String>> subList = new ArrayList<>();
FileWriter fileWriter = new FileWriter(geoJsonPath,true);
//geojson前缀
fileWriter.append("{\"type\":\"FeatureCollection\",\"features\":[");
//判断是否选择了过滤条件
if(null != conditionName && !"".equals(conditionName) && null != conditionValue && !"".equals(conditionValue)) {
for (int i = 0; i < list.size(); i++) {
Map<String,String> item = list.get(i);
if(item.get(conditionName).equals(conditionValue)) {
subList.add(item);
}
}
}else {
subList = list;
}
//写入筛选后的需要写入的内容
for (int i = 0; i < subList.size(); i++) {
Map<String,String> item = list.get(i);
fileWriter.append("{\"type\":\"Feature\",\"properties\":{");
String nameItem = (null != item.get(mapping.get("name")) ? item.get(mapping.get("name")) : "name_"+i);
fileWriter.append("\"name\":"+"\""+nameItem+"\",");
fileWriter.append("\"describe\":"+"\""+item.get(mapping.get("describe"))+"\"");
fileWriter.append("},");
Map<String,String> map = parseCoordinate(list.get(i).get("the_geom"));
String geometryType = map.get("type");
fileWriter.append("\"geometry\":{\"type\":\""+geometryType+"\",\"coordinates\":");
String coordinate = map.get("value");
fileWriter.append(coordinate);
if(i==subList.size()-1) {
fileWriter.append("}}");
}else {
fileWriter.append("}},");
}
}
fileWriter.append("]}");
fileWriter.flush();
fileWriter.close();
}
/**
* 将坐标转换成geojson格式,并标注坐标类型:Polygon-面;LineString-线;Point-点
* @param polygon 获取到的the_geom坐标字符串
* @return Map<String,String> type:坐标类型;value:转换后的geojson格式坐标
*/
public Map<String,String> parseCoordinate(String polygon){
Map<String,String> param = new HashMap<>();
String value="";
if(polygon.indexOf("(((")>0 && polygon.lastIndexOf(")))")>0) {//面
int beginIndex=polygon.indexOf("(((")+3;
int endIndex=polygon.lastIndexOf(")))");
String s=polygon.substring(beginIndex,endIndex).replace('(', ' ').replace(')', ' ');
value = geojsonWrapper(s);
param.put("type", "Polygon");
param.put("value", value);
}else if(polygon.indexOf("((")>0 && polygon.lastIndexOf("))")>0 && polygon.indexOf("(((")==-1) {//线
int beginIndex=polygon.indexOf("((")+2;
int endIndex=polygon.lastIndexOf("))");
String s=polygon.substring(beginIndex,endIndex).replace('(', ' ').replace(')', ' ');
value = geojsonWrapperLine(s);
param.put("type", "LineString");
param.put("value", value);
}else if(polygon.indexOf("(")>0 && polygon.lastIndexOf(")")>0 && polygon.indexOf("((")==-1){//点
int beginIndex=polygon.indexOf("(")+1;
int endIndex=polygon.lastIndexOf(")");
String s=polygon.substring(beginIndex,endIndex).replace('(', ' ').replace(')', ' ');
value = geojsonWrapperPoint(s);
param.put("type", "Point");
param.put("value", value);
}
return param;
}
//点
private String geojsonWrapperPoint(String point){
StringBuilder sber=new StringBuilder(point.length()+30);
String tmp[]=point.split(",");
sber.append("[");
for(int i=0;i<tmp.length;i++){
sber.append(tmp[i].trim().replace(" ", ","));
if(i != tmp.length-1)
sber.append(",");
}
sber.append("]");
return sber.toString();
}
//线
private String geojsonWrapperLine(String polygon){
StringBuilder sber=new StringBuilder(polygon.length()+30);
String tmp[]=polygon.split(",");
sber.append("[");
for(int i=0;i<tmp.length;i++){
sber.append("[");
sber.append(tmp[i].trim().replace(" ", ","));
sber.append("]");
if(i != tmp.length-1)
sber.append(",");
}
sber.append("]");
return sber.toString();
}
//面
private String geojsonWrapper(String polygon){
StringBuilder sber=new StringBuilder(polygon.length()+30);
String tmp[]=polygon.split(",");
sber.append("[[");
for(int i=0;i<tmp.length;i++){
sber.append("[");
sber.append(tmp[i].trim().replace(" ", ","));
sber.append("]");
if(i != tmp.length-1)
sber.append(",");
}
sber.append("]]");
return sber.toString();
}
}
4.swing界面实现
private ShapeFileServer shapefileServer = new ShapeFileServer();
private String shpPath = "";
private String fileName = "";
private String nameStr="";
private String describeStr="";
private String savePath = "";
public void swingShow() {
//Font font= new Font("隶书",Font.PLAIN,15);
//UIManager.put("Button.font",font);
// 确保一个漂亮的外观风格
JFrame.setDefaultLookAndFeelDecorated(true);
// 创建及设置窗口
JFrame frame = new JFrame("Cellsys数据转换工具");
//设置窗体风格
//frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
//设置窗口大小
frame.setSize(500, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
//关闭窗口即退出程序
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//布局对象
JPanel panel = new JPanel();
// 添加面板
frame.add(panel);
panel.setLayout(null);
panel.setBounds(400, 200, 200, 200);
/*
* 创建组件对象
*/
//文件名称显示框
JLabel shp = new JLabel("shp文件");
shp.setBounds(10,30,60,40);
//文件名称显示框
JLabel jl = new JLabel();
jl.setBorder(BorderFactory.createLineBorder(Color.BLACK));
jl.setBounds(80,30,270,40);
//文件选择按钮
JButton jb = new JButton("浏览");
jb.setBounds(360,30,70,40);
//mapping文本框
JLabel mapping = new JLabel("映射字段");
mapping.setBounds(10, 90,60,40);
//name文本框
JLabel nameJLabel = new JLabel("name:");
nameJLabel.setBounds(80, 90,50,40);
//字段name下拉框
JComboBox<String> nameComboBox=new JComboBox<String>();
nameComboBox.setBounds(135, 90, 110, 40);
//describe文本框
JLabel describeJLabel = new JLabel("describe:");
describeJLabel.setBounds(255, 90,60,40);
//字段describe下拉框
JComboBox<String> describeComboBox=new JComboBox<String>();
describeComboBox.setBounds(320, 90, 110, 40);
//保存路径文本框
JLabel exportJLabel = new JLabel("输出路径");
exportJLabel.setBounds(10, 150,60,40);
//输出路径显示
JLabel exportShowJLabel = new JLabel();
exportShowJLabel.setBounds(80, 150,270,40);
exportShowJLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
//文件存放路径选择
JButton export = new JButton("浏览");
export.setBounds(360,150,70,40);
//确认转换按钮
JButton submit = new JButton("确认转换");
submit.setBounds(200,210,90,40);
//显示转换后的文件存储的路径,或者提示选错文件
JLabel promptJLabel = new JLabel();
promptJLabel.setBounds(10, 260,300,60);
/*
* 将组件对象添加进布局对象panel
*/
panel.add(shp);
panel.add(jb);
panel.add(jl);
panel.add(mapping);
panel.add(nameJLabel);
panel.add(nameComboBox);
panel.add(describeJLabel);
panel.add(describeComboBox);
panel.add(exportJLabel);
panel.add(exportShowJLabel);
panel.add(export);
panel.add(submit);
panel.add(promptJLabel);
/*
* 各种事件监听器
*/
//名称下拉框,选中点击事件
nameComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
nameStr = nameComboBox.getSelectedItem().toString();
}
});
//描述下拉框,选中点击事件
describeComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
describeStr = describeComboBox.getSelectedItem().toString();
}
});
//监听文件选择按钮的事件
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
jfc.showDialog(new JLabel(), "选择");
File file=jfc.getSelectedFile();
if(file.isFile()){
//将选中的文件路径赋值全局
shpPath = file.getAbsolutePath();
String name = jfc.getSelectedFile().getName();
//判断选中的是否是SHP格式文件
String[] items = name.split("\\.");
if("shp".equals(items[items.length-1]) || "SHP".equals(items[items.length-1])) {
//获取不带拓展名的文件名称
fileName = name.substring(0, name.length()-4);
//替换选择文件的文件名显示框内容
jl.setText(shpPath);
//替换下拉框的内容
String[] model = shapefileServer.getFeatureName(shpPath);
nameComboBox.setModel(new DefaultComboBoxModel<>(model));
describeComboBox.setModel(new DefaultComboBoxModel<>(model));
}else {
//提示选择的不是shp类型文件
promptJLabel.setText("选择的不是SHP文件,请重新选择!");
}
}else {
promptJLabel.setText("选择的不是SHP文件,请重新选择!");
}
}
});
//选择文件保存路径按钮的事件监听
export.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
jfc.showDialog(new JLabel(), "选择");
File file=jfc.getSelectedFile();
if(file.isDirectory()){
//将选中的文件夹路径赋值全局
savePath = file.getAbsolutePath();
exportShowJLabel.setText(savePath);
}else {
promptJLabel.setText("请选择文件夹作为存储路径");
}
}
});
//确认转换的按钮事件监听
submit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<Map<String, String>> contentList = shapefileServer.reaferShp(shpPath);
Map<String,String> mapping = new HashMap<>();
mapping.put("name", nameStr);
mapping.put("describe", describeStr);
try {
shapefileServer.appendToFile(contentList, mapping, savePath+"/"+fileName+".geojson");
promptJLabel.setText("转换成功,转换后的文件路径:"+savePath);
} catch (IOException e1) {
e1.printStackTrace();
promptJLabel.setText("转换失败!");
}
}
});
// 设置界面可见
frame.setVisible(true);
}
5.打包运行
- 启动类
public static void main( String[] args ){
SwingServer swingServer = new SwingServer();
swingServer.swingShow();
}
- 通过runnable jar file方式打成jar包,可以将第三方jar导入其中。打包好双击就可以运行。
6.问题
以上代码在转换多组件的SHP文件时,会出现图层混杂问题。目前没有作出处理,欢迎各位码友告知处理办法。