• 纯Java实现Google地图的KMZ和KML文件的解析


    目录

    前言

    一、关于KMZ和KML

    1、KMZ是什么

    2、KML是什么

    二、Java解析实例

    1、POM.xml引用

    2、KML 基类定义

    3、空间对象的定义

    4、Kml解析工具类

    三、KML文件的解析

    1、KML解析测试

    2、KMZ解析测试

    四、总结


    前言

            今天是六.一儿童节,在这里祝各位大朋友们儿童节快乐,同时祝祖国的所有花朵们更加快乐。童年的欢乐可以治愈一切。不知道各位的儿童节是怎么度过的呀,是在陪孩子呢,还在在享受自己的欢乐时光,只愿大家都欢乐就好。这是写在最前面祝福的话,愿我们都开心快乐。

            最近碰到有朋友咨询,大致的问题是,他在项目中要实现KMZ数据的解析和WebGIS的可视化。刚好他用的技术栈是Java,同时KMZ的解析在各个网站上的相关解析代码不多。有很多代码是解析KML的,但是解析KMZ的相对比较少。一时没有参考的例子,希望能结合JAVA讲一下如何进行KMZ数据的解析。其实话说回来,虽然大致了解KMZ是什么数据,但是在之前的项目过程中,接触的空间数据也基本都是shp、gdb等等,至于google的KMZ还真的是第一回接触。

            本文主要讲解如何用JAVA语言,直接解析KMZ数据。文章首先介绍google地图中的KMZ和KML数据,然后使用代码的方式实现数据的解析,最后展示解析成果以及如何将数据转换成空间WKT数据。关于JAVA解析KML的博客和资料有不少,但是KMZ文件的还是比较稀少的,供各位朋友在工作中解析KMZ文件有一个参考。

    一、关于KMZ和KML

            在进行相关文件的解析之前,首先我们来看一下KMZ和KML这两种文件,先了解这两种文件是什么?用来做什么的,具体的文件内容是什么样的。本节主要提供这些基础知识的讲解。

    1、KMZ是什么

            KMZ 文件包含主 KML 文件以及0个或多个用 ZIP 格式打包成一个单元的支持文件(称为归档)。然后,KMZ 文件就可以作为单个实体进行存储和通过电子邮件发送。NetworkLink 可从网络服务器提取 KMZ 文件。将 KMZ 文件解压缩后,主 .kml 文件及其支持文件便分离成其各自的原始格式和目录结构,以及原始文件名和扩展名。除了变成归档格式外,ZIP 格式也会受到压缩,因此归档只能包含一个大型 KML 文件。根据 KML 文件的内容,此过程通常会产生10:1的压缩。10千字节的 KML 文件可以用1千字节的 KMZ 文件来提供。

            KMZ是Google Earth默认的输出文件格式,是一个经过ZIP格式压缩过的KML文件,当我们从网站上下载KMZ文件的时候,Windows会把KMZ文件认成ZIP文件,所以另存的时候文件后缀会被改成.ZIP,因此需要手动将文件后缀改成.KMZ。   KMZ文件用ZIP工具软件打开,然后解压缩即可得到原始KML文件。当然,KMZ文件也有自己的好处,就是KMZ文件的自身可以包含影像,这样就可以不依赖引用网络上的截图。   一般情况下,双击KMZ/KML文件即可从Google Earth中打开地标文件,但是需要注意的是,KMZ/KML地标文件名不能包含中文字符,文件存放的路径也不能有中文字符,否则将无法在Google Earth中打开。

            这里我们以漂亮国的全球基地为说明,验证一下上述的内容。把KMZ文件的后缀名修改为zip,然后用压缩文件打开。可以看到以下的文件:

            总结一下,KMZ就是把KML文件,进行了一个打包。这个很重要,在后面的解析过程中,会用到这个知识点。讲完了KMZ,下面介绍一下KML。

    2、KML是什么

            KML 代表 钥匙孔标记语言。此 GIS 格式基于 XML,主要用于 Google 地球。KML由Keyhole Inc开发,后来被Google收购.KMZ(KML-Zipped)取代KML成为默认的Google地球地理空间格式,因为它是文件的压缩版本。KML/KMZ于2008年成为开放地理空间联盟的国际标准。经度和纬度分量(十进制度)由 1984 年世界大地测量系统 (WGS84) 定义。垂直分量(高度)以米为单位从 WGS84 EGM96 大地水准面垂直基准面开始测量。

            KML (keyhole markup language)是以XML语言为基础开发的一种文件格式,用来描述和存储地理信息数据(点、线、面、图片等),是纯粹的xml文本格式,可用记事本打开编辑,所以kml文件很小。KML跟XML文件最大的不同就是KML描述的是地理信息数据。最早开发KML的是keyhole公司,2004年Goole收购keyhole并用KML开发GooleEarth。KML是原先的Keyhole客户端进行读写的文件格式,是一种XML描述语言,并且是文本格式,这种格式的文件对于Google Earth程序设计来说有极大的好处,程序员可以通过简单的几行代码读取出地标文件的内部信息,并且还可以通过程序自动生成KML文件,因此,使用KML格式的地标文件非常利于Google Earth应用程序的开发。

            这里我们还是以上面的kml文件为说明,将打开的示例xml文件内容展示如下:

    1. "1.0" encoding="UTF-8"?>
    2. <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
    3. <Document>
    4. <Folder>
    5. <name>Point Featuresname>
    6. <description>Point Featuresdescription>
    7. <Placemark>
    8. <description>Airportdescription>
    9. <name>name>
    10. <Point>
    11. <coordinates>-80.0408900000,32.8985600000,0coordinates>
    12. Point>
    13. Placemark>
    14. <Placemark>
    15. <description>Airportdescription>
    16. <name>name>
    17. <Point>
    18. <coordinates>-110.8822600000,32.1652200000,0coordinates>
    19. Point>
    20. Placemark>
    21. Folder>
    22. Document>
    23. kml>

            以上就是一个KML文件的示例,其主体内容就是一个XML。它以XML为主体,用来存储地理空间数据。因此对KML数据的解析,其本质就是对XML文件的解析。

    二、Java解析实例

            本节主要以代码实战的方式介绍使用Java编程语言实现对KML语言和KMZ语言的解析。由于涉及到xml的解析,这里不采用最原始的dom解析方式。对于KML语言,有成熟的组件de.micromata.jak.JavaAPIforKml对KML的解析。这里对相关的解析组件进行介绍:

    序号组件名称作用
    1de.micromata.jak.JavaAPIforKmlKML文件解析
    2org.apache.commons.commons-compress压缩包解压
    3com.vividsolutions.jtsJTS wkt字符串构建

    1、POM.xml引用

    1. <project xmlns="http://maven.apache.org/POM/4.0.0"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>com.yelanggroupId>
    6. <artifactId>gdal_demo1artifactId>
    7. <version>0.0.1-SNAPSHOTversion>
    8. <name>gdal_demo1name>
    9. <description>试验description>
    10. <properties>
    11. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    12. <maven.compiler.source>1.8maven.compiler.source>
    13. <maven.compiler.target>1.8maven.compiler.target>
    14. properties>
    15. <dependencies>
    16. <dependency>
    17. <groupId>de.micromata.jakgroupId>
    18. <artifactId>JavaAPIforKmlartifactId>
    19. <version>2.2.1version>
    20. dependency>
    21. <dependency>
    22. <groupId>org.apache.commonsgroupId>
    23. <artifactId>commons-compressartifactId>
    24. <version>1.21version>
    25. dependency>
    26. <dependency>
    27. <groupId>com.vividsolutionsgroupId>
    28. <artifactId>jtsartifactId>
    29. <version>1.13version>
    30. dependency>
    31. dependencies>
    32. project>

    2、KML 基类定义

            这里进行kml 基类定义,将name、description、List进行统一封装。针对Point、Polygon、Polyline对象,在自己的对象属性中扩展额外的属性。这里采用OOP的实现方式。网上很多的代码没有将父级类抽象出来,同时其代码只解析了name。没有解析description属性。这里我们将描述信息同样解析出来。关键代码如下:

    1. package com.yelang.kmzcase;
    2. import java.util.List;
    3. import de.micromata.opengis.kml.v_2_2_0.Coordinate;
    4. /**
    5. * kml 基类,将name、description、List进行统一封装
    6. * @author 夜郎king
    7. */
    8. public class KmlBaseEntity {
    9. private List points;
    10. private String name;
    11. private String description;
    12. public List getPoints() {
    13. return points;
    14. }
    15. public void setPoints(List points) {
    16. this.points = points;
    17. }
    18. public String getName() {
    19. return name;
    20. }
    21. public void setName(String name) {
    22. this.name = name;
    23. }
    24. public String getDescription() {
    25. return description;
    26. }
    27. public void setDescription(String description) {
    28. this.description = description;
    29. }
    30. public KmlBaseEntity(List points, String name, String description) {
    31. super();
    32. this.points = points;
    33. this.name = name;
    34. this.description = description;
    35. }
    36. public KmlBaseEntity() {
    37. super();
    38. }
    39. }

    3、空间对象的定义

            空间对象常见的类型包括点(Point)、线(Polyline)、面(Polygon)三种类型。这里我们将根据需要定义不同的空间对象。下面分别给出实例代码:

    KmlPoint.java

    1. package com.yelang.kmzcase;
    2. import java.util.List;
    3. import de.micromata.opengis.kml.v_2_2_0.Coordinate;
    4. public class KmlPoint extends KmlBaseEntity{
    5. private String color;
    6. public String getColor() {
    7. return color;
    8. }
    9. public void setColor(String color) {
    10. this.color = color;
    11. }
    12. public KmlPoint(List points,String name,String description,String color){
    13. super(points, name, description);
    14. this.color = color;
    15. }
    16. public KmlPoint() {
    17. super();
    18. }
    19. }

    KmlLine.java 

    1. package com.yelang.kmzcase;
    2. public class KmlLine extends KmlBaseEntity {
    3. private String color;
    4. private long width;
    5. public String getColor() {
    6. return color;
    7. }
    8. public void setColor(String color) {
    9. this.color = color;
    10. }
    11. public long getWidth() {
    12. return width;
    13. }
    14. public void setWidth(long width) {
    15. this.width = width;
    16. }
    17. }

    KmlPolygon.java

    1. package com.yelang.kmzcase;
    2. /**
    3. * @program: 面状实体
    4. **/
    5. public class KmlPolygon extends KmlBaseEntity {
    6. private String color;
    7. public String getColor() {
    8. return color;
    9. }
    10. public void setColor(String color) {
    11. this.color = color;
    12. }
    13. }

    4、Kml解析工具类

            这里定义Kml的解析工具类,主要负责解析KML,然后根据不同的图层,将属性和空间坐标点信息赋值给不同的空间数据集合。网上有一些解析的代码,仅解析name属性。这里扩展了其它的属性,包括描述属性。详细代码如下:

    1. package com.yelang.kmzcase;
    2. import de.micromata.opengis.kml.v_2_2_0.*;
    3. import java.io.File;
    4. import java.io.InputStream;
    5. import java.util.ArrayList;
    6. import java.util.List;
    7. /**
    8. * @description: KML文件解析
    9. **/
    10. public class ParsingKmlUtil {
    11. /**
    12. * 解析kml文件
    13. */
    14. public KmlData parseKmlByFile(File file) {
    15. Kml kml = Kml.unmarshal(file);
    16. return getByKml(kml);
    17. }
    18. /**
    19. * 解析kml文件流
    20. *
    21. * @param inputstream
    22. * @return
    23. */
    24. public KmlData parseKmlByInputstream(InputStream inputstream) {
    25. Kml kml = Kml.unmarshal(inputstream);
    26. return getByKml(kml);
    27. }
    28. /**
    29. * Kml对象转自定义存储对象
    30. *
    31. * @param kml
    32. * @return
    33. */
    34. public KmlData getByKml(Kml kml) {
    35. KmlData kmlData = new KmlData();
    36. kmlData.setKmlPoints(new ArrayList<>());
    37. kmlData.setKmlLines(new ArrayList<>());
    38. kmlData.setKmlPolygons(new ArrayList<>());
    39. Feature feature = kml.getFeature();
    40. parseFeature(feature, kmlData);
    41. return kmlData;
    42. }
    43. /**
    44. * 解析kml节点
    45. * @param feature
    46. * @param kmlData
    47. */
    48. private void parseFeature(Feature feature, KmlData kmlData) {
    49. if (feature != null) {
    50. if (feature instanceof Document) {
    51. List featureList = ((Document) feature).getFeature();
    52. featureList.forEach(documentFeature -> {
    53. if (documentFeature instanceof Placemark) {
    54. getPlaceMark((Placemark) documentFeature, kmlData);
    55. } else {
    56. parseFeature(documentFeature, kmlData);
    57. }
    58. });
    59. } else if (feature instanceof Folder) {
    60. List featureList = ((Folder) feature).getFeature();
    61. featureList.forEach(documentFeature -> {
    62. if (documentFeature instanceof Placemark) {
    63. getPlaceMark((Placemark) documentFeature, kmlData);
    64. } else {
    65. parseFeature(documentFeature, kmlData);
    66. }
    67. });
    68. }
    69. }
    70. }
    71. private void getPlaceMark(Placemark placemark, KmlData kmlData) {
    72. Geometry geometry = placemark.getGeometry();
    73. /*String name = placemark.getName();
    74. placemark.getDescription();
    75. System.out.println(placemark.getDescription());
    76. if (name == null) {
    77. name = placemark.getDescription();
    78. }
    79. parseGeometry(name, geometry, kmlData);*/
    80. parseGeometry(placemark,geometry,kmlData);
    81. }
    82. /**
    83. * 解析点线面形状的数据分别放入存储对象
    84. * @param placemark placemark对象
    85. * @param geometry 形状类型
    86. * @param kmlData 存储对象
    87. */
    88. private void parseGeometry(Placemark placemark, Geometry geometry, KmlData kmlData) {
    89. if (geometry != null) {
    90. if (geometry instanceof Polygon) {
    91. Polygon polygon = (Polygon) geometry;
    92. Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
    93. if (outerBoundaryIs != null) {
    94. LinearRing linearRing = outerBoundaryIs.getLinearRing();
    95. if (linearRing != null) {
    96. List coordinates = linearRing.getCoordinates();
    97. if (coordinates != null) {
    98. outerBoundaryIs = ((Polygon) geometry).getOuterBoundaryIs();
    99. addPolygonToList(kmlData.getKmlPolygons(), placemark, outerBoundaryIs);
    100. }
    101. }
    102. }
    103. } else if (geometry instanceof LineString) {
    104. LineString lineString = (LineString) geometry;
    105. List coordinates = lineString.getCoordinates();
    106. if (coordinates != null) {
    107. coordinates = ((LineString) geometry).getCoordinates();
    108. addLineStringToList(kmlData.getKmlLines(), coordinates, placemark);
    109. }
    110. } else if (geometry instanceof Point) {
    111. Point point = (Point) geometry;
    112. List coordinates = point.getCoordinates();
    113. if (coordinates != null) {
    114. coordinates = ((Point) geometry).getCoordinates();
    115. addPointToList(kmlData.getKmlPoints(), coordinates, placemark);
    116. }
    117. } else if (geometry instanceof MultiGeometry) {
    118. List geometries = ((MultiGeometry) geometry).getGeometry();
    119. for (Geometry geometryToMult : geometries) {
    120. Boundary outerBoundaryIs;
    121. List coordinates;
    122. if (geometryToMult instanceof Point) {
    123. coordinates = ((Point) geometryToMult).getCoordinates();
    124. addPointToList(kmlData.getKmlPoints(), coordinates, placemark);
    125. } else if (geometryToMult instanceof LineString) {
    126. coordinates = ((LineString) geometryToMult).getCoordinates();
    127. addLineStringToList(kmlData.getKmlLines(), coordinates, placemark);
    128. } else if (geometryToMult instanceof Polygon) {
    129. outerBoundaryIs = ((Polygon) geometryToMult).getOuterBoundaryIs();
    130. addPolygonToList(kmlData.getKmlPolygons(), placemark, outerBoundaryIs);
    131. }
    132. }
    133. }
    134. }
    135. }
    136. /**
    137. * 保存面状数据
    138. *
    139. * @param kmlPolygonList 已有面状数据
    140. * @param placemark placemark对象
    141. * @param outerBoundaryIs 面状信息
    142. */
    143. private void addPolygonToList(List kmlPolygonList, Placemark placemark, Boundary outerBoundaryIs) {
    144. LinearRing linearRing = outerBoundaryIs.getLinearRing();// 面
    145. KmlPolygon kmlPolygon = new KmlPolygon();
    146. kmlPolygon.setPoints(linearRing.getCoordinates());
    147. kmlPolygon.setName(placemark.getName());
    148. kmlPolygon.setDescription(placemark.getDescription());
    149. kmlPolygonList.add(kmlPolygon);
    150. }
    151. /**
    152. * 保存线状数据
    153. *
    154. * @param kmlLineList 已有线状数据
    155. * @param coordinates 线状经纬度数据
    156. * @param name 线状名称
    157. */
    158. private void addLineStringToList(List kmlLineList, List coordinates, Placemark placemark) {
    159. KmlLine kmlLine = new KmlLine();
    160. kmlLine.setPoints(coordinates);
    161. kmlLine.setName(placemark.getName());
    162. kmlLine.setDescription(placemark.getDescription());
    163. kmlLineList.add(kmlLine);
    164. }
    165. /**
    166. * 保存点状数据
    167. *
    168. * @param kmlPointList 已有点状数据
    169. * @param coordinates 点状经纬度数据
    170. * @param name 点状名称
    171. */
    172. private void addPointToList(List kmlPointList, List coordinates, Placemark placemark) {
    173. KmlPoint kmlPoint = new KmlPoint();
    174. kmlPoint.setName(placemark.getName());
    175. kmlPoint.setDescription(placemark.getDescription());
    176. kmlPoint.setPoints(coordinates);
    177. kmlPointList.add(kmlPoint);
    178. }
    179. }

            在定义了上述的代码之后,基本就可以实现了纯Java对KML文件的解析。下一节将调用上面的代码进行相应文件的解析。

    三、KML文件的解析

            本节将重点介绍如何解析KML文件。

    1、KML解析测试

    1. package com.yelang.kmzcase;
    2. import org.apache.commons.compress.archivers.ArchiveEntry;
    3. import org.apache.commons.compress.archivers.ArchiveInputStream;
    4. import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
    5. import com.vividsolutions.jts.geom.GeometryFactory;
    6. import com.vividsolutions.jts.io.WKTWriter;
    7. import de.micromata.opengis.kml.v_2_2_0.Coordinate;
    8. import de.micromata.opengis.kml.v_2_2_0.Kml;
    9. import java.io.*;
    10. import com.vividsolutions.jts.geom.*;
    11. public class KMZParser {
    12. public static void parseKml() throws IOException {
    13. ParsingKmlUtil parsingKmlUtil = new ParsingKmlUtil();
    14. File file = new File("C:/BaiduDownload/美军基地-地图数据(kmz)/美空军基地 - 副本/US-AFB.KML"); // 文件地址自己修改
    15. KmlData kmlData = parsingKmlUtil.parseKmlByFile(file);
    16. // assert kmlData != null;
    17. if (kmlData.getKmlPoints().size() > 0) {
    18. for (KmlPoint k : kmlData.getKmlPoints()) {
    19. GeometryFactory geoFactory = new GeometryFactory();
    20. Coordinate coord = k.getPoints().get(0);
    21. com.vividsolutions.jts.geom.Coordinate jtCoord = new com.vividsolutions.jts.geom.Coordinate(coord.getLongitude(), coord.getLatitude(), coord.getAltitude());
    22. // 使用GeometryFactory创建一个点
    23. Geometry point = geoFactory.createPoint(jtCoord);
    24. WKTWriter writer = new WKTWriter();
    25. String wkt = writer.write(point);
    26. System.out.println(k.getPoints() + "\t"+ wkt +"\t"+ k.getDescription() + "\t " + k.getName());
    27. }
    28. }
    29. }
    30. // 使用示例
    31. public static void main(String[] args) throws IOException {
    32. KMZParser.parseKml();
    33. }
    34. }

            由于在XML中的坐标是一个数组,如果想把这些数据保存到空间数据库中,需要进行格式转换,比如从WKT字符串转为Geometry。当然,保存到空间数据库中,有很多种方法,这里我们介绍一种,基于JTS的方式构建WKT字符串,因为在MyBatis-Plus中,可以直接操作WKT字符串。将坐标转换WKT字符串的方法如下:

    1. com.vividsolutions.jts.geom.Coordinate jtCoord = new com.vividsolutions.jts.geom.Coordinate(coord.getLongitude(), coord.getLatitude(), coord.getAltitude());
    2. // 使用GeometryFactory创建一个点
    3. Geometry point = geoFactory.createPoint(jtCoord);
    4. WKTWriter writer = new WKTWriter();
    5. String wkt = writer.write(point);

            在控制台中执行以上方法可以看到以下信息的输出,说明KML文件解析成功。

    1. [-80.04089,32.89856] POINT (-80.04089 32.89856) Airport CHARLESTON AFB/INTL 查尔斯顿空军基地/国际机场
    2. [-110.88226,32.16522] POINT (-110.88226 32.16522) Airport DAVIS-MONTHAN AFB 戴维斯-蒙森空军基地
    3. [-110.34393,31.58844] POINT (-110.34393 31.58844) Airport LIBBY AAF/SIERRA VISTA MUN 利比空军基地/谢拉维斯塔
    4. [-98.49243,33.98621] POINT (-98.49243 33.98621) Airport SHEPPARD AFB/WICHITA FALLS MUN 谢泼德空军基地/威奇托福尔斯??
    5. [-72.52899,42.19849] POINT (-72.52899 42.19849) Airport WESTOVER ARB/METROPOLITAN 韦斯特欧弗空军基地
    6. [-84.04541,39.82544] POINT (-84.04541 39.82544) Airport WRIGHT-PATTERSON AFB 赖特-帕特森空军基地
    7. [-84.07013,39.80072] POINT (-84.07013 39.80072) Airport WRIGHT-PATTERSON AFB 赖特-帕特森空军基地

    2、KMZ解析测试

            网上很多博客都只讲了如何解析KML,但是对于KMZ的解析介绍比较少,以JAVA为开发语言解析更少了。上面的方法也只实现了KML的解析,如果把文件换成KMZ,肯定会报错的。不信来试试。错误信息如下:

             如果发生了以上的异常,不要急。发生这个异常的原因其实在文章的开头就讲过了。如果看到这里前面没有印象的,可以翻到前面去看一下。还是简单说明一下吧,主要是KMZ是KML的压缩包,而以上代码是KML的解析,没有对KMZ进行解压。这里有两种方法来实现,第一种是将KMZ文件进行解压,然后对解压后的文件解析,肯定没问题。第二种是在压缩包中读取,然后对压缩流信息进行解析。第一种方式会增加不必要的脏文件,第二种则不会,因为原始文件只有一个。 下面我们采用第二种实现方式,首先来定义一个处理接口(必须要):

    1. package com.yelang.kmzcase;
    2. import java.io.IOException;
    3. import java.io.InputStream;
    4. /**
    5. * kml转换类,用于实现kml的自定义识别与读取
    6. * @author 夜郎king
    7. */
    8. public interface IKMLParser {
    9. /**
    10. * @param kmlInputStream
    11. * @throws IOException
    12. */
    13. void parseKML(InputStream kmlInputStream) throws IOException;
    14. }

            然后再定义针对KMZ的内容解析代码(基于在线解压的方式),然后已输入流的方式完成内容解析,这个代码网上比较少,如果需要KMZ文件解析,可以作为参考:

    1. public static void parseKMZFile(File kmzFile, IKMLParser kmlParser) throws IOException {
    2. try (InputStream fileInputStream = new FileInputStream(kmzFile);
    3. ArchiveInputStream archiveInputStream = new ZipArchiveInputStream(fileInputStream)) {
    4. ArchiveEntry entry;
    5. while ((entry = archiveInputStream.getNextEntry()) != null) {
    6. String name = entry.getName();
    7. if (name.toLowerCase().endsWith(".kml") || name.toLowerCase().endsWith(".kmz")) {
    8. // 如果发现.kml或.kmz文件,可以将其内容读取出来并传递给KMLParser处理
    9. kmlParser.parseKML(archiveInputStream);
    10. }
    11. }
    12. }
    13. }
    14. public static void parseKmz() throws IOException {
    15. File kmzFile = new File("C:/BaiduDownload/美军基地-地图数据(kmz)/美国全球基地.kmz");
    16. KMZParser.parseKMZFile(kmzFile, new IKMLParser() {
    17. @Override
    18. public void parseKML(InputStream kmlInputStream) throws IOException {
    19. // 在这里实现你的KML解析逻辑
    20. // 例如,可以将读取的KML内容转换为字符串
    21. try (BufferedReader reader = new BufferedReader(new InputStreamReader(kmlInputStream))) {
    22. String line;
    23. StringBuffer xmlContent = new StringBuffer(1024);
    24. while ((line = reader.readLine()) != null) {
    25. // 处理每一行KML数据
    26. xmlContent.append(line);
    27. }
    28. // System.out.println(xmlContent);
    29. Kml kml = Kml.unmarshal(xmlContent.toString());
    30. ParsingKmlUtil pku = new ParsingKmlUtil();
    31. KmlData kmlData = pku.getByKml(kml);
    32. if (null != kmlData.getKmlPoints()&&kmlData.getKmlPoints().size() > 0) {
    33. for (KmlPoint kp : kmlData.getKmlPoints()) {
    34. GeometryFactory geoFactory = new GeometryFactory();
    35. Coordinate coord = kp.getPoints().get(0);
    36. com.vividsolutions.jts.geom.Coordinate jtCoord = new com.vividsolutions.jts.geom.Coordinate(coord.getLongitude(), coord.getLatitude(), coord.getAltitude());
    37. // 使用GeometryFactory创建一个点
    38. Geometry point = geoFactory.createPoint(jtCoord);
    39. WKTWriter writer = new WKTWriter();
    40. String wkt = writer.write(point);
    41. System.out.println(kp.getPoints() + "\t"+ wkt +"\t"+ kp.getDescription() + "\t " + kp.getName());
    42. }
    43. System.out.println("美军全球基地的数据是==>" + kmlData.getKmlPoints().size());
    44. }
    45. } catch (IOException e) {
    46. e.printStackTrace();
    47. }
    48. }
    49. });
    50. }

            上述代码的主要逻辑是,使用compress对KMZ文件进行在线解压,然后动态拼接KML内容,最后解析KML文件,然后提取空间信息。经过上述步骤,完成信息的解析。在运行以上的代码,发现KMZ文件已经成功解析。

            至此已经完成KMZ和KML文件的解析。 

    四、总结

            以上就是本文的主要内容,本文主要讲解如何用JAVA语言,直接解析KMZ数据。文章首先介绍google地图中的KMZ和KML数据,然后使用代码的方式实现数据的解析,最后展示解析成果以及如何将数据转换成空间WKT数据。关于JAVA解析KML的博客和资料有不少,但是KMZ文件的还是比较稀少的,算是作为网文的一种补充,供各位朋友在工作中解析KMZ文件有一个参考。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。

            博文在编写过程中参考了以下博文:

            1、什么是 KMZ 文件?

            2、从事地信测绘必须知道的GIS常见数据格式类型,以及数据格式和扩展名汇总

            3、地理信息地图标记KML与KMZ的区别

            4、java 生成kml 文件

            5、Java解析kml文件获取点/线段/多边形面状地图经纬度信息

  • 相关阅读:
    Python重要知识点filter_map_partial_reduce_sorted内置函数的使用方法
    Python测试题12道(含答案)
    运维工程师——学习路线技能图谱
    C++环形缓冲区
    如何在github上面找到想要的sdk以及Python使用Etcd集群基础教程
    论文阅读11——《Mutual Boost Network for Attributed Graph Clustering》
    C++ 之 queue、stack、dueque队列
    leetcode:801. 使序列递增的最小交换次数【线性dp + 考虑当前和前一位 + java】
    判断DataFrame中是否存在具有相同内容的行将具有相同内容的行进行标记和处理
    基于Feign接口的全链路拦截器
  • 原文地址:https://blog.csdn.net/yelangkingwuzuhu/article/details/139375604