技术背景

  KML,是标记语言(Keyhole Markup Language)的缩写,最初由Keyhole公司开发,是一种基于XML 语法与格式的、用于描述和保存地理信息(如点、线、图像、多边形和模型等)的编码规范,可以被 Google Earth 和 Google Maps 识别并显示。

  创建这个工具只是因为一次偶然的需求,因为要将一个2G的点云数据导到Google Earth上进行显示,手动编辑绝对是不可能的,所以临时创建了这个小工具,为了方便使用,添加了一些简易的操作界面,这样便可以批量写入经纬度三维坐标数据(含高程)至kml文件内,然后导入Google Earth进行显示。关于kml文件的内部格式这里就不再详细描述了,具体内容请查看参考博客1【KML地图文件解析】。下面具体讲述一下程序设计原理。

实现原理

  本程序核心原理是很简单的,首先将.csv(或.txt)文件(内部格式为B,L,H 一行一个点坐标)读取以后,创建kml文件的头,然后根据kml文件的固定格式,将数据写入,最后文件写入完成以后,添加上文件的尾部格式。文件选择采用的是JFileChooser,具体使用方法请查看参考博客2【swing中JFileChooser的用法】。

  最后是界面的简要制作,添加两个控件,一个是用来选择文件的,另一个为程序退出按钮。不再具体阐述了,原理比较简单,直接上代码吧。

具体实现

  项目结构

  核心部分

  1 package main;
2
3 import java.io.BufferedWriter;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.FileOutputStream;
7 import java.io.FileReader;
8 import java.io.FileWriter;
9 import java.io.IOException;
10 import java.io.LineNumberReader;
11 import java.io.PrintStream;
12 import javax.swing.JFileChooser;
13 import javax.swing.JLabel;
14
15 public class BlhToKml {
16
17 /**
18 * @param args
19 */
20 public static String InputFilePath;
21 public static String OutputFilePath;
22 @SuppressWarnings("static-access")
23 public static void main() throws IOException{
24 JFileChooser jfc=new JFileChooser();
25 jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
26 jfc.showDialog(new JLabel(), "选择文件");
27 File file = jfc.getSelectedFile();
28 if(file == null){
29 return;
30 }
31 String FilePath = file.getAbsolutePath();
32 InputFilePath=FilePath;
33 OutputFilePath=InputFilePath;
34 if(OutputFilePath.indexOf(".")>=0)
35 {
36 OutputFilePath = OutputFilePath.substring(0, OutputFilePath.lastIndexOf("."));
37 }else{
38 return;
39 }
40 OutputFilePath=OutputFilePath+".kml";
41 //System.out.println(OutputFilePath);
42 WriteHeadInformationToFile1();
43 WriteHeadInformationToFile2();
44 ReplacePointInformation();
45 WriteEndInformationToFile();
46 TipFrame TF = new TipFrame();
47 TF.tishifu("已经转换完成!");
48 }
49 //将标题写入到指定路径下的文本内
50 public static void WriteHeadInformationToFile1() {
51 String filePath = OutputFilePath;
52 try {
53 File file = new File(filePath);
54 PrintStream ps = new PrintStream(new FileOutputStream(file));
55 ps.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
56 ps.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\"\r\n");
57 } catch (FileNotFoundException e){
58 e.printStackTrace();
59 }
60 }
61 public static void WriteHeadInformationToFile2(){
62 String filePath = OutputFilePath;
63 try {
64 FileWriter fw = new FileWriter(filePath, true);
65 BufferedWriter bw = new BufferedWriter(fw);
66 bw.write("xmlns:atom=\"http://www.w3.org/2005/Atom\">\r\n");
67 bw.write("<Document>\r\n");
68 bw.write("\t<name>Placemark.kml</name>\r\n");
69 bw.write("\t<Style id=\"sh_placemark_circle_highlight\">\r\n");
70 bw.write("\t\t<IconStyle>\r\n");
71 bw.write("\t\t\t<color>ff0000ff</color>\r\n");
72 bw.write("\t\t\t<scale>0.8</scale>\r\n");
73 bw.write("\t\t\t<Icon>\r\n");
74 bw.write("\t\t\t\t<href>http://maps.google.com/mapfiles/kml/shapes/open-diamond.png</href>\r\n");
75 bw.write("\t\t\t</Icon>\r\n");
76 bw.write("\t\t</IconStyle>\r\n");
77 bw.write("\t\t<ListStyle>\r\n");
78 bw.write("\t\t</ListStyle>\r\n");
79 bw.write("\t</Style>\r\n");
80 bw.write("\t<StyleMap id=\"msn_placemark_circle\">\r\n");
81 bw.write("\t\t<Pair>\r\n");
82 bw.write("\t\t\t<key>normal</key>\r\n");
83 bw.write("\t\t\t<styleUrl>#sn_placemark_circle</styleUrl>\r\n");
84 bw.write("\t\t</Pair>\r\n");
85 bw.write("\t\t<Pair>\r\n");
86 bw.write("\t\t\t<key>highlight</key>\r\n");
87 bw.write("\t\t\t<styleUrl>#sh_placemark_circle_highlight</styleUrl>\r\n");
88 bw.write("\t\t</Pair>\r\n");
89 bw.write("\t</StyleMap>\r\n");
90 bw.close();
91 fw.close();
92 } catch (Exception e) {
93 e.printStackTrace();
94 }
95 }
96 public static void ReplacePointInformation() throws IOException {
97 String filePath = OutputFilePath;
98 File sourceFile = new File(InputFilePath);
99 int lineNum = getTotalLines(sourceFile);
100 try {
101 FileWriter fw = new FileWriter(filePath, true);
102 BufferedWriter bw = new BufferedWriter(fw);
103 for(int i = 0;i<lineNum;i++){
104 bw.write("\t<Placemark>\r\n");
105 bw.write("\t\t<styleUrl>#msn_placemark_circle</styleUrl>\r\n");
106 bw.write("\t\t<Point>\r\n");
107 String str1=readAppointedLineNumber(sourceFile, i+1);
108 bw.write("\t\t\t<coordinates>"+str1+",</coordinates>\r\n");
109 bw.write("\t\t</Point>\r\n");
110 bw.write("\t</Placemark>\r\n");
111 }
112 bw.close();
113 fw.close();
114 } catch (Exception e) {
115 e.printStackTrace();
116 }
117 }
118 public static void WriteEndInformationToFile() {
119 String filePath = OutputFilePath;
120 try {
121 FileWriter fw = new FileWriter(filePath, true);
122 BufferedWriter bw = new BufferedWriter(fw);
123 bw.write("</Document>\r\n");
124 bw.write("</kml>");
125 bw.close();
126 fw.close();
127 } catch (Exception e) {
128 e.printStackTrace();
129 }
130 }
131 // 读取文件指定行。
132 public static String readAppointedLineNumber(File sourceFile, int lineNumber)
133 throws IOException {
134 FileReader in = new FileReader(sourceFile);
135 LineNumberReader reader = new LineNumberReader(in);
136 String s = "";
137 if (lineNumber <= 0 || lineNumber > getTotalLines(sourceFile)) {
138 System.out.println("不在文件的行数范围(1至总行数)之内。");
139 System.exit(0);
140 }
141 int lines = 0;
142 while (s != null) {
143 lines++;
144 s = reader.readLine();
145 if((lines - lineNumber) == 0) {
146 //System.out.println(s);
147 return s;
148 }
149 }
150 reader.close();
151 in.close();
152 return s;
153 }
154 // 文件内容的总行数。
155 public static int getTotalLines(File file) throws IOException {
156 FileReader in = new FileReader(file);
157 LineNumberReader reader = new LineNumberReader(in);
158 String s = reader.readLine();
159 int lines = 0;
160 while (s != null) {
161 lines++;
162 s = reader.readLine();
163 if(lines>=2){
164 if(s!=null){
165 //System.out.println(s+"$");
166 }
167 }
168 }
169 reader.close();
170 in.close();
171 //System.out.println(lines);
172 return lines;
173 }
174 }

  窗体部分1-主界面

  1 package main;
2
3 import java.awt.Color;
4 import java.awt.FlowLayout;
5 import java.awt.Font;
6 import java.awt.Frame;
7 import java.awt.Label;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
10 import java.awt.event.WindowAdapter;
11 import java.awt.event.WindowEvent;
12 import java.io.IOException;
13 import javax.swing.JButton;
14 import javax.swing.JLabel;
15 import javax.swing.JPanel;
16
17 public class Frame1 {
18
19 /**
20 * @param args
21 */
22 public static void main(String[] args) {
23 // TODO Auto-generated method stub
24 major_Frame();
25 }
26 public static void major_Frame(){
27 final Frame major = new Frame("KML转换器");
28 major.setLayout(new FlowLayout(FlowLayout.CENTER));
29 major.setBounds(400, 300, 430, 250);
30 major.setBackground(new Color(255,255,255));
31 JPanel jPanel = new JPanel();//创建jPanel
32 jPanel.setBackground(new Color(255,255,255) );
33 jPanel.add(new JLabel("<html><br>\t每一行的数据属性为:精度,纬度,高程。每一个数据之间用英<br>" +
34 "文逗号隔开。<br><br><br></html>"));//为jPanel添加JLabel
35 Label label1 = new Label("格式提示");
36 label1.setFont(new Font("",1,18));//字体大小
37 label1.setBounds(100,200,400,200);
38 major.add(label1);
39 major.add(jPanel);
40 JButton btn1 = new JButton("输入");
41 btn1.addActionListener(new ActionListener(){
42 @SuppressWarnings("unused")
43 public void actionPerformed(ActionEvent arg0) {
44 // TODO Auto-generated method stub
45 BlhToKml blhtokml = new BlhToKml();
46 try {
47 BlhToKml.main();
48 } catch (IOException e) {
49 // TODO Auto-generated catch block
50 e.printStackTrace();
51 }
52 }
53
54 });
55 JButton btn2 = new JButton("退出");
56 btn2.addActionListener(new ActionListener(){
57 public void actionPerformed(ActionEvent e) {
58 major.setVisible(false);
59 System.exit(0);
60 }
61 });
62 major.add(btn1);
63 major.add(btn2);
64 major.addWindowListener(new WindowAdapter(){
65 public void windowClosing(WindowEvent e){
66 //System.exit(0);
67 major.setVisible(false);
68 major.dispose();
69 }
70 });
71 major.setVisible(true);
72 }
73
74 }

  窗体部分2-提示窗

  1 package main;
2
3 import java.awt.FlowLayout;
4 import java.awt.Font;
5 import java.awt.Frame;
6 import java.awt.GridLayout;
7 import java.awt.Label;
8 import java.awt.event.MouseEvent;
9 import java.awt.event.MouseListener;
10 import java.awt.event.WindowAdapter;
11 import java.awt.event.WindowEvent;
12 import javax.swing.JButton;
13 import javax.swing.JPanel;
14
15 public class TipFrame {
16 public static void tishifu(String str){
17 final Frame f1=new Frame("提示");
18 f1.setBounds(500, 300, 300, 160);
19 f1.setResizable(false);
20 f1.setLayout(new GridLayout(2,1));
21 JPanel jpanel1 = new JPanel(new FlowLayout(FlowLayout.CENTER));
22 Label label1 = new Label(str);
23 label1.setFont(new Font("",1,15));
24 jpanel1.add(label1);
25 f1.add(jpanel1);
26 JPanel jpanel2 = new JPanel(new FlowLayout(FlowLayout.CENTER));
27 JButton Yes =new JButton("确定");
28 jpanel2.add(Yes);
29 f1.add(jpanel2);
30 f1.addWindowListener(new WindowAdapter() {
31 public void windowClosing(WindowEvent e) {
32 //System.exit(0);
33 f1.setVisible(false);
34 f1.dispose();
35 }
36 });
37 Yes.addMouseListener(new MouseListener(){
38 @Override
39 public void mouseClicked(MouseEvent arg0) {
40 // TODO 自动生成的方法存根
41 }
42 @Override
43 public void mouseEntered(MouseEvent arg0) {
44 // TODO 自动生成的方法存根
45 }
46 @Override
47 public void mouseExited(MouseEvent arg0) {
48 // TODO 自动生成的方法存根
49 }
50 public void mousePressed(MouseEvent arg0) {
51 // TODO 自动生成的方法存根
52 f1.setVisible(false);
53 f1.dispose();
54 }
55 @Override
56 public void mouseReleased(MouseEvent arg0) {
57 // TODO 自动生成的方法存根
58 }
59 });
60 f1.setVisible(true);
61 }
62 }

运行效果

  主窗体

  选择窗体

  提示窗

运行结果

  测试数据(部分)

  成果数据(部分)

  接下来导入到Google Earth就可以了

  至此,小工具设计完成了!

  源码我已经上传至博客园了,下载地址:https://files.cnblogs.com/files/thyou/BLH_to_KML.zip,希望能对使用kml文件这方面的同学有一丝帮助。

致谢

  感谢以下参考博客博主对于相关技术的分享交流,衷心感谢!

参考博客

1、KML地图文件解析【https://blog.csdn.net/onlymydreams_mfc/article/details/81840232】

2、swing中JFileChooser的用法【https://www.cnblogs.com/happyPawpaw/archive/2013/04/27/3046414.html】

经纬坐标(BLH)数据创建.kml文件小工具设计 Java版的更多相关文章

  1. 基于UDP传输协议局域网文件接收软件设计 Java版

    网路传输主要的两大协议为TCP/IP协议和UDP协议,本文主要介绍基于UDP传输的一个小软件分享,针对于Java网络初学者是一个很好的练笔,大家可以参考进行相关的联系,但愿能够帮助到大家. 话不多说, ...

  2. Swift - 从字典(或者Alamofire)直接创建Model文件的工具

    Swift - 从字典(或者Alamofire)直接创建Model文件的工具 效果 1. 常规生成model的方式 2. 通过debug创建model的方式 特性 1. 可以处理JSON格式的字典数据 ...

  3. WPF根据Oracle数据库的表,生成CS文件小工具

    开发小工具的原因: 1.我们公司的开发是客户端用C#,服务端用Java,前后台在通讯交互的时候,会用到Oracle数据库的字段,因为服务器端有公司总经理开发的一个根据Oracle数据库的表生成的cla ...

  4. WPF做的迁移文件小工具

    客户这边需要往服务器上传PDF文件.然后PDF文件很多,需要挑出来的PDF文件也不少.因此做了个小工具. 功能很简单,选定源文件夹,选定记录着要提取的文件的excel 文件.OK ,界面如下. XAM ...

  5. sqluldr2 oracle直接导出数据为文本的小工具使用

    近期客户有需求,导出某些审计数据,供审计人进行核查,只能导出成文本或excel格式的进行查看,这里我们使用sqluldr2工具进行相关数据的导出. oracle导出数据为文本格式比较麻烦,sqluld ...

  6. 【分享】生成Revit扩展的addin文件小工具

    在进行Revit二次开发的时候,加载命令/程序使用的是添加addin文件的方式,每次都需要手动的写,而且参数有好多,很不方便.于是乎我有了写一个小工具的想法.进过研究终于完成了.主要使用RevitAd ...

  7. 应用程序初次运行数据库配置小程序(Java版)

    应用程序初始化数据库配置小程序 之前写过一个Java版的信息管理系统,但部署系统的时候还需要手动的去配置数据库和导入一些初始化的数据才能让系统运行起来,所以我在想是不是可以写一个小程序在系统初次运行的 ...

  8. python实现文件搜索工具(简易版)

    在python学习过程中有一次需要进行GUI 的绘制, 而在python中有自带的库tkinter可以用来简单的GUI编写,于是转而学习tkinter库的使用. 学以致用,现在试着编写一个简单的磁文件 ...

  9. Duplicate Manager Pro for Mac(重复文件查找工具)破解版安装

    1.软件简介    Duplicate Manager Pro 是 macOS 系统上一款重复文件查找工具,可以帮你在 Mac 电脑上查找出磁盘上面的重复文件,然后让你对这些重复文件进行判断并删除,使 ...

随机推荐

  1. elasticsearch在linux上的安装,Centos7.X elasticsearch 7.6.2安装

    本文环境:Elasticsearch7.6.2目前最先版本   centos7.X     JDK1.8 elasticsearch介绍 官网:https://www.elastic.co/cn/pr ...

  2. 【代码优化】Bean映射之MapStruct

    [代码优化]Bean映射之MapStruct 一.背景 领域模型相互转换就只能靠手工的 get()/set()? 普遍的做法有以下几种: 手工 get()/set(): 构造器: BeanUtils ...

  3. CTF-sql-宽字节注入

    本文章主要涉及sql宽字节注入注入的原理讲解,如有错误,望指出.(附有目录,如需查看请点右下角) 一.首先介绍一下本篇文章所用到的知识点: 常用到的url编码: 空格:%20 单引号:%27 在sql ...

  4. gin中绑定查询字符串或表单数据

    package main import ( "github.com/gin-gonic/gin" "log" "time" ) type P ...

  5. java抽象类概述特点

    1 package face_09; 2 /* 3 * 抽象类: 4 * 抽象:笼统,模糊,看不懂!不具体. 5 * 6 * *特点: 7 * 1,方法只有声明没有实现时,该方法就是抽象方法,需要被a ...

  6. Java应用程序OOM分析

    内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用. 内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢 ...

  7. 安卓开发常见Bug-setContentView(R.layout.....)报错

    这是安卓开发的常见错误,当你在引用或者复制别人的Layout xml文件时需要在AndroidManifest.xml中添加东西 需要将图中的activity android:name添加进去,否则是 ...

  8. java 中的多线程简单介绍

    package com.zxf.demo; /* * 多线程的实现方式两种? * 一..实现 runnable 接口 * 2.重写run方法 Run():当一个线程启动后,就会自动执行该方法 * 3. ...

  9. 关于spring MVC 绑定json字符串与实体类绑定

    1 如果前台传json字符串,后台用@RequestBody 接收 前端 "content-Type":"application/json", 2  前台用fo ...

  10. 使用 TensorFlow 构建机器学习项目中文版&#183;翻译完成

    原文:Building Machine Learning Projects with TensorFlow 协议:CC BY-NC-SA 4.0 不要担心自己的形象,只关心如何实现目标.--<原 ...