根据geotools自己封装的工具类,主要有shp文件的内容读取,转geojson,要素的增删改,新shp生成
需要的依赖
这里主要用的是geotools的依赖,版本是<geotools.version>23.2</geotools.version>
还用到了fastjson,版本1.2.57
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.57</version>
</dependency>
<!-- geotools -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-cql</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-ysld</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-hsql</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-extension</artifactId>
<version>${geotools.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.geotools/gt-main -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-opengis</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-xml</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-referencing</artifactId>
<version>${geotools.version}</version>
</dependency>
如果不好下需要指定一下repository
<repository>
<id>GeoSolutions</id>
<url>http://maven.geo-solutions.it/</url>
</repository>
读取工具
public class ShapeFileReaderUtils {
/**
* 校验shp文件
*
* @param fileUrl 文件地址 shp或shp文件夹
* @return File
* @throws Exception e
*/
public static File checkShapeFile(String fileUrl) throws Exception {
File file = new File(fileUrl);
if (file.isDirectory()) {
File[] fa = file.listFiles();
if (fa == null || fa.length < 1) {
throw new Exception("找不到shp文件");
}
boolean flag = true;
for (File f : fa) {
if (new ShpFiles(file).exists(ShpFileType.SHP)) {
file = f;
flag = false;
break;
}
}
if (flag) {
throw new Exception("找不到shp文件");
}
} else {
if (!new ShpFiles(file).exists(ShpFileType.SHP)) {
throw new Exception("找不到shp文件");
}
}
return file;
}
/**
* shp文件要素源
*
* @param fileUrl 文件地址
* @return ContentFeatureSource
* @throws Exception e
*/
public static ContentFeatureSource getFeatureSourceFromShapeFile(String fileUrl) throws Exception {
ShapefileDataStore sds = null;
try {
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
File file = checkShapeFile(fileUrl);
sds = (ShapefileDataStore) dataStoreFactory.createDataStore(file.toURI().toURL());
String type = sds.getTypeNames()[0];
sds.setCharset(getShapeFileCharsetName(fileUrl));
return sds.getFeatureSource(type);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
assert sds != null;
sds.dispose();
}
}
/**
* 获取要素几何类型
*
* @param featureSource 要素源
* @return 几何类型
*/
public static String getGeometryTypeName(SimpleFeatureSource featureSource) {
SimpleFeatureType schema = featureSource.getSchema();
return schema.getGeometryDescriptor().getType().getName().toString();
}
/**
* shp转geoJsonArray
*
* @param fileUrl 文件地址
* @return JSONArray
*/
public static JSONArray shapeFileToJsonArray(String fileUrl) throws IOException {
JSONArray array = new JSONArray();
FeatureJSON featureJSON = new FeatureJSON();
FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = null;
try {
ContentFeatureSource featureSource = getFeatureSourceFromShapeFile(fileUrl);
assert featureSource != null;
featureReader = featureSource.getReader();
while (featureReader.hasNext()) {
SimpleFeature feature = featureReader.next();
StringWriter writer = new StringWriter();
featureJSON.writeFeature(feature, writer);
JSONObject json = JSONObject.parseObject(String.valueOf(writer));
array.add(json);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (featureReader != null) {
featureReader.close();
}
}
return array;
}
/**
* shp转geoJsonArray
*
* @param fileUrl shp文件地址
* @param filter Filter 参考https://docs.geotools.org/latest/userguide/library/main/filter.html
* @return JSONArray
*/
public static JSONArray shapeFileToJsonArray(String fileUrl, Filter filter) throws IOException {
JSONArray array = new JSONArray();
FeatureJSON featureJSON = new FeatureJSON();
FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = null;
try {
ContentFeatureSource featureSource = getFeatureSourceFromShapeFile(fileUrl);
assert featureSource != null;
featureReader = featureSource.getReader(filter);
while (featureReader.hasNext()) {
SimpleFeature feature = featureReader.next();
StringWriter writer = new StringWriter();
featureJSON.writeFeature(feature, writer);
JSONObject json = JSONObject.parseObject(String.valueOf(writer));
array.add(json);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (featureReader != null) {
featureReader.close();
}
}
return array;
}
/**
* 获取shp几何对象集合
*
* @param fileUrl 文件地址
* @return 几何集合
*/
public static List<Geometry> getGeometryList(String fileUrl) throws IOException {
List<Geometry> geometryList = new ArrayList<>();
ShapefileReader r = null;
try {
r = new ShapefileReader(new ShpFiles(fileUrl), false, false, new GeometryFactory());
while (r.hasNext()) {
Geometry shape = (Geometry) r.nextRecord().shape();
geometryList.add(shape);
}
} catch (Exception e) {
if (r != null) {
r.close();
}
e.printStackTrace();
}
return geometryList;
}
/**
* 带过滤器的获取shp几何方法
* 使用FeatureReader而不是ShapefileReader,效率可能会低一些
*
* @param fileUrl shp文件地址
* @param filter Filter 参考https://docs.geotools.org/latest/userguide/library/main/filter.html
* @return List<Geometry>
*/
public static List<Geometry> getGeometryList(String fileUrl, Filter filter) throws IOException {
List<Geometry> geometryList = new ArrayList<>();
FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = null;
try {
ContentFeatureSource featureSource = getFeatureSourceFromShapeFile(fileUrl);
assert featureSource != null;
featureReader = featureSource.getReader(filter);
//遍历featureCollection
while (featureReader.hasNext()) {
SimpleFeature feature = featureReader.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
geometryList.add(geom);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (featureReader != null) {
featureReader.close();
}
}
return geometryList;
}
/**
* 读取shp属性表
*
* @param path dbf路径
* @return JSONArray
*/
public static JSONArray getAttributesList(String path) {
JSONArray array = new JSONArray();
JSONObject object = null;
Charset charSet = getShapeFileCharsetName(path);
// try()的括号中可以写多行声明,每个声明的变量类型都必须是Closeable的子类,用分号隔开,自动close
try (DbaseFileReader reader = new DbaseFileReader(new ShpFiles(path), false, charSet)) {
DbaseFileHeader header = reader.getHeader();
int numFields = header.getNumFields();
//迭代读取记录
while (reader.hasNext()) {
try {
Object[] entry = reader.readEntry();
object = new JSONObject();
for (int i = 0; i < numFields; i++) {
String title = header.getFieldName(i);
Object value = entry[i];
object.put(title, value);
}
} catch (Exception e) {
e.printStackTrace();
}
array.add(object);
}
} catch (Exception e) {
e.printStackTrace();
}
//关闭
return array;
}
/**
* shp转geoJsonObject
*
* @param fileUrl 文件地址
* @return JSONObject
*/
public static JSONObject ShapeFileToGeoJsonObject(String fileUrl) throws IOException {
JSONObject res = new JSONObject();
res.put("type", "FeatureCollection");
res.put("features", shapeFileToJsonArray(fileUrl));
return res;
}
public static JSONObject ShapeFileToGeoJsonObject(String fileUrl, Filter filter) throws IOException {
JSONObject res = new JSONObject();
res.put("type", "FeatureCollection");
res.put("features", shapeFileToJsonArray(fileUrl, filter));
return res;
}
/**
* 高版本arcgis生成的shp会有一个cpg文件记录编码格式
*
* @param path shp路径
* @return 编码格式
*/
static Charset getShapeFileCharsetName(String path) {
path = path.replaceAll(".shp", ".cpg");
File pFile = new File(path);
String encode = "GBK";
if (!pFile.exists() || !pFile.isFile()) {
return Charset.forName(encode);
}
File file = new File(path);
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String tempString;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
// 显示行号
if ("UTF-8".equals(tempString.toUpperCase())) {
encode = "UTF-8";
break;
}
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return Charset.forName(encode);
}
}
写入工具
public class ShapeFileWriterUtils {
/**
* 单个过滤器的要素移除
*
* @param match Filter 参考https://docs.geotools.org/latest/userguide/library/main/filter.html
* @param path shp路径
* @throws IOException e
*/
public static void removeFeatures(Filter match, String path) throws Exception {
ShapefileDataStore shapefileDataStore = getShpDataStore(path);
String typeName = shapefileDataStore.getTypeNames()[0];
SimpleFeatureStore dataStore = (SimpleFeatureStore) shapefileDataStore.getFeatureSource(typeName);
Transaction transaction = new DefaultTransaction("remove");
dataStore.setTransaction(transaction);
try {
dataStore.removeFeatures(match);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
transaction.close();
}
}
/**
* 多个过滤器的要素移除 单纯记录下FilterFactory2用法,建议条件自己写成单个的
*
* @param match Filter 参考https://docs.geotools.org/latest/userguide/library/main/filter.html
* @param path shp路径
* @throws IOException e
*/
public static void removeFeatures(List<Filter> match, String path) throws Exception {
// 多个filter可以这样拼成一个
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
Filter filter = ff.or(match);
Filter filterAnd = ff.and(match);
removeFeatures(filter, path);
}
/**
* 修改shp文件要素的属性
*
* @param attributeName 属性字段名
* @param attributeValue 属性值
* @param filter 查询filter
* @param path 文件路径
* @throws IOException e
*/
public static void modifyFeatures(String[] attributeName, Object[] attributeValue, Filter filter, String path) throws Exception {
ShapefileDataStore shapefileDataStore = getShpDataStore(path);
Transaction transaction = new DefaultTransaction("modify");
String typeName = shapefileDataStore.getTypeNames()[0];
SimpleFeatureStore dataStore = (SimpleFeatureStore) shapefileDataStore.getFeatureSource(typeName);
dataStore.setTransaction(transaction);
try {
dataStore.modifyFeatures(attributeName, attributeValue, filter);
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
} finally {
transaction.close();
}
}
/**
* 给现有shp增加要素
*
* @param featureCollection SimpleFeatureCollection
* @param path shp路径
* @throws Exception e
*/
public static void appendFeature(SimpleFeatureCollection featureCollection, String path) throws Exception {
// 创建输出数据存储
ShapefileDataStore shpDataStore = getShpDataStore(path);
SimpleFeatureType inputSchema = featureCollection.getSchema();
SimpleFeatureType dataStoreSchema = shpDataStore.getSchema();
if (FeatureTypes.equals(inputSchema, dataStoreSchema)) {
throw new Exception("error! featureCollection schema not equals to dataStore schema!");
}
addFeatureTransaction(shpDataStore, featureCollection);
}
/**
* 生成shp
*
* @param featureCollection SimpleFeatureCollection
* @param path 输出路径 shp结尾
* @throws IOException e
*/
public static void buildShp(SimpleFeatureCollection featureCollection, String path) throws Exception {
// 创建输出数据存储
ShapefileDataStore newDataStore = getShpDataStore(path);
SimpleFeatureType type = featureCollection.getSchema();
// 设置输出数据存储
newDataStore.createSchema(type);
// 设置坐标系
newDataStore.forceSchemaCRS(type.getCoordinateReferenceSystem());
addFeatureTransaction(newDataStore, featureCollection);
}
/**
* geoJson文件转shp
*
* @param geoJson geoJson文件
* @param path 文件输出地址 .shp结尾
* @throws IOException e
*/
public static void geoJSON2Shp(File geoJson, String path) throws Exception {
InputStream in = new FileInputStream(geoJson);
geoJSON2Shp(in, path);
}
/**
* geoJson转shp 流式
*
* @param input geoJson流
* @param path 文件输出地址 .shp结尾
* @throws IOException e
*/
public static void geoJSON2Shp(InputStream input, String path) throws Exception {
FeatureJSON fjson = new FeatureJSON(new GeometryJSON(15));
FeatureIterator<SimpleFeature> jsonIt = fjson.streamFeatureCollection(input);
if (!jsonIt.hasNext()) {
throw new IllegalArgumentException(
"Cannot create shapefile. GeoJSON stream is empty");
}
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = null;
try {
// 创建输出数据存储
ShapefileDataStore shpDataStore = getShpDataStore(path);
// use feature type of first feature
SimpleFeature firstFeature = jsonIt.next();
shpDataStore.createSchema(firstFeature.getFeatureType());
writer = shpDataStore.getFeatureWriterAppend(
shpDataStore.getTypeNames()[0], Transaction.AUTO_COMMIT);
addFeature(firstFeature, writer);
while (jsonIt.hasNext()) {
SimpleFeature feature = jsonIt.next();
addFeature(feature, writer);
}
} finally {
if (writer != null) {
writer.close();
}
}
}
/**
* 若文件存在,返回该shp;若不存在,创建新dataStore
*
* @param path 文件路径
* @return ShapefileDataStore
* @throws IOException e
*/
private static ShapefileDataStore getShpDataStore(String path) throws Exception {
File newFile = new File(path);
ShapefileDataStore inputDataStore;
if (newFile.exists()) {
inputDataStore = (ShapefileDataStore) DataStoreFinder.getDataStore(
Collections.singletonMap("url", newFile.toURI().toURL()));
} else {
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
inputDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(
Collections.singletonMap("url", newFile.toURI().toURL()));
}
inputDataStore.setCharset(getShapeFileCharsetName(path));
return inputDataStore;
}
private static void addFeatureTransaction(ShapefileDataStore dataStore, SimpleFeatureCollection featureCollection) throws IOException {
Transaction transaction = new DefaultTransaction("create");
String typeName = dataStore.getTypeNames()[0]; // shp文件名称?
SimpleFeatureStore featureStore = (SimpleFeatureStore) dataStore.getFeatureSource(typeName);
// 写入要素
featureStore.setTransaction(transaction);
try {
featureStore.addFeatures(featureCollection);
transaction.commit();
} catch (Exception problem) {
problem.printStackTrace();
transaction.rollback();
} finally {
transaction.close();
}
}
private static void addFeature(SimpleFeature feature, FeatureWriter<SimpleFeatureType, SimpleFeature> writer) throws IOException {
SimpleFeature toWrite = writer.next();
for (int i = 0; i < toWrite.getType().getAttributeCount(); i++) {
String name = toWrite.getType().getDescriptor(i).getLocalName();
toWrite.setAttribute(name, feature.getAttribute(name));
}
// copy over the user data
if (feature.getUserData().size() > 0) {
toWrite.getUserData().putAll(feature.getUserData());
}
// perform the write
writer.write();
}
}
使用示例
当初写的测试类,并没有全用到
public class SHPUtilTest {
private static SimpleFeatureType createFeatureType() throws FactoryException {
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
// set global state
builder.setName("Location");
// 设置坐标系的几种方式
// builder.setCRS(DefaultGeographicCRS.WGS84); // <- Coordinate reference system
// builder.setCRS(CRS.decode("EPSG:4326")); // <- Coordinate reference system
builder.setSRS("EPSG:4326");
// add attributes in order
builder.add("the_geom", Point.class);
builder.length(15).add("Name", String.class); // <- 15 chars width for name field
builder.length(15).add("number", Integer.class);
// build the type
return builder.buildFeatureType();
}
public static void write1() {
try {
// 定义要素类型
final SimpleFeatureType TYPE = createFeatureType();
DefaultFeatureCollection collection = new DefaultFeatureCollection("internal", TYPE);
GeometryFactory geometryFactory = new GeometryFactory();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
// 设置属性
double latitude = Double.parseDouble("117.123456789");
double longitude = Double.parseDouble("35.320001");
String Name = "2050003092";
String Number = "0";
// 使用geometryFactory 创建要素
Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude));
Object[] obj = {point, Name, Number};
// 使用SimpleFeatureBuilder创建要素
SimpleFeature feature = featureBuilder.buildFeature(null, obj);
collection.add(feature);
ShapeFileWriterUtils.appendFeature(collection, "D:\\newPoi.shp");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void copy1(String inPath, String outPath) throws Exception {
File inFile = new File(inPath);
if (!inFile.exists()) {
throw new Exception("inFile not exist");
}
File outFile = new File(outPath);
// Read
DataStore inputDataStore = DataStoreFinder.getDataStore(
Collections.singletonMap("url", inFile.toURI().toURL()));
String inputTypeName = inputDataStore.getTypeNames()[0];
SimpleFeatureType inputType = inputDataStore.getSchema(inputTypeName);
FeatureSource<SimpleFeatureType, SimpleFeature>
source = inputDataStore.getFeatureSource(inputTypeName);
FeatureCollection<SimpleFeatureType, SimpleFeature>
inputFeatureCollection = source.getFeatures();
// Write
ShapefileDataStoreFactory dataStoreFactory =
new ShapefileDataStoreFactory();
ShapefileDataStore newDataStore =
(ShapefileDataStore) dataStoreFactory.createNewDataStore(
Collections.singletonMap("url", outFile.toURI().toURL()));
newDataStore.createSchema(inputType);
String typeName = newDataStore.getTypeNames()[0];
SimpleFeatureStore featureStore =
(SimpleFeatureStore) newDataStore.getFeatureSource(typeName);
featureStore.addFeatures(inputFeatureCollection);
}
public static void queryFeatures() throws Exception {
Filter filter = CQL.toFilter("Name = '2050003092'");
ShapeFileWriterUtils.removeFeatures(filter, "D:\\newPoi.shp");
}
public static void modifyTest() throws Exception {
String path = "D:\\test.shp";
Filter filter = CQL.toFilter("river_name = ''");
String[] attrs = new String[]{"river_name", "county_id", "city_id"};
Object[] values = new Object[]{"无名河", "320503", "320500"};
ShapeFileWriterUtils.modifyFeatures(attrs, values, filter, path);
}
public static void main(String[] args) throws Exception {
modifyTest();
}
}