需要注意的问题是,当表字段的长度大于10,在往shape文件写数据时会报错,可以将字段截取前10位
第一步,根据如下的sql语句找到srtext信息,这个信息是在生成shapefile文件时,设置坐标系的
SELECT st_srid(shape) FROM sde.ele_bil_a ORDER BY objectid asc limit 1
SELECT srtext FROM public.sde_spatial_references where srid=4326
srtext的信息列子如下
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]
引入依赖
<repositories> <repository> <id>OSGeo-Repository</id> <name>OSGeo-Repository</name> <url>https://repo.osgeo.org/repository/release</url> </repository> </repositories>
<dependency> <groupId>org.geotools</groupId> <artifactId>gt-shapefile</artifactId> <version>24.0</version> <exclusions> <exclusion> <artifactId>commons-text</artifactId> <groupId>org.apache.commons</groupId> </exclusion> </exclusions> </dependency>
import org.apache.commons.lang3.StringUtils;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.referencing.crs.DefaultEngineeringCRS;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.WKTReader;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ShapeUtil {
private static Logger LOG = LoggerFactory.getLogger(ShapeUtil.class);
/**
* 生成shape文件
*
* @param shpPath 生成shape文件路径(包含文件名称)
* @param encode 编码
* @param geoType 图幅类型,Point和Rolygon
* @param geoms 图幅集合
*/
public static void write2Shape(String shpPath, String encode, String geoType, List<Geometry> geoms) {
try {
//创建shape文件对象
File file = new File(shpPath);
Map<String, Serializable> params = new HashMap<>();
params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
//定义图形信息和属性信息
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
tb.setCRS(DefaultGeographicCRS.WGS84);
tb.setName("shapefile");
if ("Polygon".equals(geoType)) {
tb.add("the_geom", Polygon.class);
} else if ("MultiPolygon".equals(geoType)) {
tb.add("the_geom", MultiPolygon.class);
} else if ("Point".equals(geoType)) {
tb.add("the_geom", Point.class);
} else if ("MultiPoint".equals(geoType)) {
tb.add("the_geom", MultiPoint.class);
} else if ("LineString".equals(geoType)) {
tb.add("the_geom", LineString.class);
} else if ("MultiLineString".equals(geoType)) {
tb.add("the_geom", MultiLineString.class);
} else {
throw new Exception("Geometry中没有该类型:" + geoType);
}
ds.createSchema(tb.buildFeatureType());
//设置编码
Charset charset = Charset.forName(encode);
ds.setCharset(charset);
//设置Writer
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
for (Geometry geom : geoms) {
//String type = geom.getGeometryType();
//写下一条
SimpleFeature feature = writer.next();
feature.setAttribute("the_geom", geom);
}
writer.write();
writer.close();
ds.dispose();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成shape文件
*
* @param shpPath 生成shape文件路径(包含文件名称)
* @param encode 编码
* @param geoType 图幅类型,Point和Rolygon
* @param shpKey data中图幅的key
* @param attrKeys 属性key集合
* @param data 图幅和属性集合
*/
public static boolean write2Shape(String shpPath, String encode, String geoType, String shpKey, List<String> attrKeys, List<Map<String, Object>> data, String srtext) {
File file = new File(shpPath);
Map<String, Serializable> params = new HashMap<>();
ShapefileDataStore ds = null;
try {
if (data == null || data.size() == 0) {
return false;
}
// 根据SRID创建坐标参考系统
CoordinateReferenceSystem crs = null;
if(StringUtils.isNotBlank(srtext)){
try {
crs = CRS.parseWKT(srtext);
} catch (Exception e) {
LOG.error("---------crs error...");
}
}
//创建shape文件对象
params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
//定义图形信息和属性信息
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
if(crs != null){
tb.setCRS(crs);
}else {
LOG.info("crs is null...");
tb.setCRS(DefaultGeographicCRS.WGS84);
}
tb.setName("shapefile");
if ("Polygon".equals(geoType)) {
tb.add("the_geom", Polygon.class);
} else if ("MultiPolygon".equals(geoType)) {
tb.add("the_geom", MultiPolygon.class);
} else if ("Point".equals(geoType)) {
tb.add("the_geom", Point.class);
} else if ("MultiPoint".equals(geoType)) {
tb.add("the_geom", MultiPoint.class);
} else if ("LineString".equals(geoType)) {
tb.add("the_geom", LineString.class);
} else if ("MultiLineString".equals(geoType)) {
tb.add("the_geom", MultiLineString.class);
} else {
throw new Exception("Geometry中没有该类型:" + geoType);
}
for (String field : attrKeys) {
tb.add(field, String.class);
}
ds.createSchema(tb.buildFeatureType());
//设置编码
Charset charset = Charset.forName(encode);
ds.setCharset(charset);
//设置Writer
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
//写入文件信息
for (int i = 0; i < data.size(); i++) {
SimpleFeature feature = writer.next();
Map<String, Object> row = data.get(i);
if(row.get(shpKey) == null){
feature.setAttribute("the_geom", null);
}else {
Geometry geom = getByWKT(row.get(shpKey).toString());
feature.setAttribute("the_geom", geom);
}
for (String key : row.keySet()) {
if (!key.equals(shpKey)) {
if (row.get(key) != null) {
feature.setAttribute(key, row.get(key).toString());
} else {
feature.setAttribute(key, "");
}
}
}
}
writer.write();
writer.close();
ds.dispose();
return true;
//添加到压缩文件
//zipShapeFile(shpPath);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(ds != null){
ds.dispose();
}
}
return false;
}
private static Geometry getByWKT(String wkt){
try {
WKTReader reader = new WKTReader();
Geometry geometry = reader.read(wkt);
return geometry;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 压缩shape文件
*
* @param shpPath shape文件路径(包含shape文件名称)
*/
public static boolean zipShapeFile(String shpPath) {
InputStream input = null;
ZipOutputStream zipOut = null;
try {
File shpFile = new File(shpPath);
String shpRoot = shpFile.getParentFile().getPath();
String shpName = shpFile.getName().substring(0, shpFile.getName().lastIndexOf("."));
String zipPath = shpRoot + File.separator + shpName + ".zip";
File zipFile = new File(zipPath);
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
// zip的名称为
zipOut.setComment(shpName);
String[] shpFiles = new String[]{
shpRoot + File.separator + shpName + ".dbf",
shpRoot + File.separator + shpName + ".prj",
shpRoot + File.separator + shpName + ".shp",
shpRoot + File.separator + shpName + ".shx",
shpRoot + File.separator + shpName + ".fix"
};
for (int i = 0; i < shpFiles.length; i++) {
File file = new File(shpFiles[i]);
input = new FileInputStream(file);
zipOut.putNextEntry(new ZipEntry(file.getName()));
int temp = 0;
while ((temp = input.read()) != -1) {
zipOut.write(temp);
}
input.close();
}
return true;
} catch (Exception e) {
LOG.error("---------------error...");
e.printStackTrace();
}finally {
if(input != null){
try {
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(zipOut != null){
try {
zipOut.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return false;
}
public static void main(String[] args) {
// zipShapeFile("C:\\file\\shp\\d35e6134999143009871aeecd52bc4cc\\ELE_BIL_P.shp");
// 根据SRID创建坐标参考系统
CoordinateReferenceSystem crs = null;
String wktString = "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]]";
try {
// crs = CRS.decode("EPSG:" + 4490);
crs = CRS.parseWKT(wktString);
System.out.println("---------------");
} catch (Exception e) {
e.printStackTrace();
// 处理异常,例如无效的SRID
}
}
}
调用实例
public String exportShp(PageRequest page) throws ParseException {
StringBuffer sql = new StringBuffer("select objectid,XZQHDM,XZQHMC,SJXZQHDM,XZQHJB,st_astext(shape) as shape from sde.XZQH");
Query query = entityManager.createNativeQuery(sql.toString(), Region.class);
List<Region> list = query.getResultList();
if(list == null || list.size() <= 0){
return null;
}
List<String> attrKeys = new ArrayList<>();
attrKeys.add("objectid");
attrKeys.add("XZQHDM");
attrKeys.add("XZQHMC");
attrKeys.add("SJXZQHDM");
attrKeys.add("XZQHJB");
attrKeys.add("shape");
List<Map<String, Object>> data = new ArrayList<>();
for (Region region : list) {
Map<String, Object> map = new HashMap<>();
map.put("objectid", region.getObjectid());
map.put("XZQHDM", region.getXZQHDM());
map.put("XZQHMC", region.getXZQHMC());
map.put("SJXZQHDM", region.getSJXZQHDM());
map.put("XZQHJB", region.getXZQHJB());
if(region.getShape() != null){
Geometry geom = WKTUtil.wktToGeom(region.getShape());
map.put("shape", geom);
}else {
map.put("shape", null);
}
data.add(map);
}
String uuid = UUIDUtils.getUUID();
String url = "C:/files/shp/" + uuid + ".shp";
ShapeUtil.write2Shape(url, "utf-8", "Polygon", "shape", attrKeys, data);
ShapeUtil.zipShapeFile(url);
return "htp://127.0.0.1/files/" + uuid + ".zip";
}
如果不知道shape的类型,可以根据这个来判断
if(StringUtils.isNotBlank(wkt)){
wkt = wkt.toUpperCase();
if(wkt.contains("MULTIPOINT")){
geoType = "MultiPoint";
}else if(wkt.contains("POINT")){
geoType = "Point";
}else if(wkt.contains("MULTIPOLYGON")){
geoType = "MultiPolygon";
}else if(wkt.contains("MULTILINESTRING")){
geoType = "MultiLineString";
}else if(wkt.contains("LINESTRING")){
geoType = "LineString";
}else if(wkt.contains("POLYGON")){
geoType = "Polygon";
}else {
LOG.info(wkt);
}
}