步骤0:你也可以参考这篇文章 :java实现geojson格式数据与shp文件相互转换
步骤1:引入引入geotools工具。
步骤2:编写工具类,获取shp的zip文件。
步骤3:编写工具类,解析shp文件成为jsonObject (geoJson)。
步骤4:拿到你的jsonObject,供你使用。
步骤1:引入geotools工具,笔者全网找半天也没在中文局域网里找到引入的方法,而是在公司同事的pom文件找到了:
<!-- shp文件解析 开始 -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.ejml</groupId>
<artifactId>ejml-ddense</artifactId>
<version>0.39</version>
</dependency>
<dependency>
<groupId>org.ejml</groupId>
<artifactId>ejml-core</artifactId>
<version>0.39</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-opengis</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-data</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-api</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-metadata</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-referencing</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>19.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>javax.measure</groupId>
<artifactId>jsr-275-1.0-beta</artifactId>
<version>2</version>
</dependency>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
</dependency>
<!-- shp文件解析 结束 -->
你也可以参考来引入geotools:Maven中GeoTools的引入 - Maven 的 repository 与 mirror
步骤2:编写工具类,编写获取shp的zip文件的方法getFeatureCollectionByShpFile()
。(该方法是为了将shp的zip压缩包解析后拿到FeatureCollection集合,其中需要自定义的 ZipUtil 解压到随机文件夹)
ShapeFileUtil工具类:
public class ShapeFileUtil {
/*
* @param zipFile: 压缩包文件地址
* @return FeatureCollection
* @author pangshicheng
* @description 解析shp压缩包,并返回解析出的 FeatureCollection
* @date 2023/7/18 16:02
*/
public static FeatureCollection getFeatureCollectionByShpFile(File zipFile) throws IOException {
try {
String tempDir = FileUtil.getTempDirPath();
File shapeDir = new File(tempDir + File.separator + new Date().getTime());
shapeDir.mkdir();
List<String> files = ZipUtil.unZipFiles(zipFile, shapeDir.getPath() + File.separator);
String shapFileName = "";
for (String fileName : files) {
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
if ("shp".equals(suffix)) {
shapFileName = fileName;
}
}
File shapeFile = new File(shapFileName);
List<SimpleFeature> list = new ArrayList<>();
Map<String, Object> shapeFileParams = new HashMap();
shapeFileParams.put("url", shapeFile.toURI().toURL());
// 设置编码
shapeFileParams.put("charset", "GBK");
DataStore dataStore = DataStoreFinder.getDataStore(shapeFileParams);
if (dataStore == null) {
throw new RuntimeException("couldn't load the damn data store: " + shapeFileParams);
}
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source = dataStore.getFeatureSource(typeName);
Filter filter = Filter.INCLUDE;
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
return collection;
}catch (Exception e){
throw e;
}
}
}
ZipUtil工具类:
/**
* @author soulmate丶
* @date 2021-10-26
*/
public class ZipUtil {
private static final Logger log = LoggerFactory.getLogger(ZipUtil.class);
/**
* 保存zip文件到本地并调用解压方法并返回解压出的文件的路径集合
*
* @param file 文件
* @return list //解压出的文件的路径合集
*/
private static String zipPath = "f:/shpfile/";//zip根路径
/**
* zip解压
*
* @param srcFile zip源文件
* @param destDirPath 解压后的目标文件夹
* @return list 解压文件的路径合集
* @throws RuntimeException 解压失败会抛出运行时异常
*/
public static List<String> unZipFiles(File srcFile, String destDirPath) throws RuntimeException {
List<String> list = new ArrayList<>();
long start = System.currentTimeMillis();
// 判断源文件是否存在
if (!srcFile.exists()) {
throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
}
// 开始解压
ZipFile zipFile = null;
try {
zipFile = new ZipFile(srcFile, Charset.forName("GBK"));
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
log.info("解压" + entry.getName());
// 如果是文件夹,就创建个文件夹
if (entry.isDirectory()) {
String dirPath = destDirPath + File.separator + entry.getName();
File dir = new File(dirPath);
dir.mkdirs();
} else {
// 如果是文件,就先创建一个文件,然后用io流把内容copy过去
File targetFile = new File(destDirPath + File.separator + entry.getName());
// 保证这个文件的父文件夹必须要存在
log.info(destDirPath + entry.getName());
list.add(destDirPath + entry.getName());
if (!targetFile.getParentFile().exists()) {
log.info("父文件不存在");
}
targetFile.createNewFile();
// 将压缩文件内容写入到这个文件中
InputStream is = zipFile.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
// 关流顺序,先打开的后关闭
fos.close();
is.close();
}
}
long end = System.currentTimeMillis();
log.info("解压完成,耗时:" + (end - start) + " ms");
} catch (Exception e) {
throw new RuntimeException("unzip error from ZipUtils", e);
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return list;
}
/**
* @param filePath 临时文件的删除
* 删除文件夹里面子目录
* 再删除文件夹
*/
public static void deleteFiles(String filePath) {
File file = new File(filePath);
if ((!file.exists()) || (!file.isDirectory())) {
log.info("file not exist");
return;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (filePath.endsWith(File.separator)) {
temp = new File(filePath + tempList[i]);
} else {
temp = new File(filePath + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
deleteFiles(filePath + "\\" + tempList[i]);
}
}
// 空文件的删除
file.delete();
}
}
步骤3:在相同工具类编写方法shpToGeoJson()
,解析shp文件成为jsonObject (geoJson)。
/**
* @param zipFile:
* @return JSONObject
* @author pangshicheng
* @description 通过shp压缩文件,将其转换为GeoJson格式
* @date 2023/7/18 16:04
*/
public static JSONObject shpToGeoJson(File zipFile) throws IOException {
FeatureJSON fjson = new FeatureJSON();
JSONObject geoJsonObject=new JSONObject();
geoJsonObject.put("type","FeatureCollection");
try {
// 获取FeatureCollection
FeatureCollection collection = getFeatureCollectionByShpFile(zipFile);
FeatureIterator iterator = collection.features();
List<JSONObject> array = new ArrayList<JSONObject>();
//遍历feature转为json对象
while (iterator.hasNext()) {
SimpleFeature feature = (SimpleFeature) iterator.next();
StringWriter writer = new StringWriter();
fjson.writeFeature(feature, writer);
String temp = writer.toString();
byte[] b = temp.getBytes("iso8859-1");
temp = new String(b, "gbk");
JSONObject json = JSONObject.parseObject(temp);
array.add(json);
}
iterator.close();
//添加到geojsonObject
geoJsonObject.put("features",array);
iterator.close();
}catch (Exception e){
throw e;
}
return geoJsonObject;
}
步骤4:拿到你的jsonObject,供你使用。
方式二:在前端使用shapefile插件来直接转换
<el-upload
v-model:file-list="uploadShpList"
:http-request="uploadSectionFile"
action="#"
multiple
:limit="1"
:data="{
bucketName: 'map',
acceptFile: 'rar'
}"
:on-success="uploadSuccess"
>
<el-button type="primary">上传矢量数据</el-button>
</el-upload>
function uploadSuccess(response, uploadFile, uploadFiles) {
console.log(response)
console.log(uploadFile)
}
function uploadSectionFile(params) {
const file = params.file
const fileName = file.name
const isZip = fileName.indexOf('zip') !== -1
const isShp = fileName.indexOf('shp') !== -1
if (!(isZip || isShp)) {
return false
} else {
loading.value = true;
isZip ? openZip(file) : toGeo(file)
}
}
// 为zip时,读取压缩包,选取shp文件
function openZip(data) {
var newZip = new JsZip()
newZip.loadAsync(data).then(function (file) {
// 压缩包里的内容file.files
const fileList = Object.keys(file.files)
const pattern = new RegExp(/\S\.shp$/)
let shpFile = fileList.find(i => pattern.test(i))
newZip.file(shpFile).async('arraybuffer') // 此处是压缩包中的shp文件,arraybuffer(此时在回调的参数中已经可以获取到上传的zip压缩包下的所有文件)
.then(function (content) { // 这个就是文件中的内容
shapeFileOpen(content)
})
}).catch(err => {
// 是否是合法的zip包,解决rar包改后缀zip
console.log(err)
})
}
// 转ArrayBuffer
function toGeo(data) {
const reader = new FileReader()
reader.readAsArrayBuffer(data)
reader.onload = function (e) {
shapeFileOpen(this.result)
}
}
// shapefile插件 shp转geo
function shapeFileOpen(content) {
let features = []
open(content).then(source => source.read().then(function log(result) {
if (result.done) {
if (features.length > 1) {
//这部分纯粹为了把很多平面拼在一起,你也可以根据自己的需求拼接
const cList = features.map(ele => {
return ele.geometry.coordinates
})
const geojson = {
type: 'Feature',
properties: {},
geometry: {
type: 'MultiPolygon',
coordinates: cList
}
}
//上传接口
} else {
//上传接口
}
return
}
features.push(result.value) //多个面时,会打印每一个,这样就先把他们放在一个集合里
return source.read().then(log)
})
).catch(error => console.error(error.stack)).finally(()=>{
let geoJson ={
type: "FeatureCollection",
name: "100000_full",
features: features
}
})
}
拿到的 geoJson 就是我们要的结果。