所以,我过去已经制作了一些样本KML / KMZ文件,主要是手工制作,并且由于这项工作已经发现了一些inconsistencies与谷歌地球。在大多数情况下,我认为我能够很好地处理特定版本的GE需要做的事情。最近,我尝试在KML / KMZ示例文件中添加一些自动化,以根据给定的点和其他元数据CSV为某些客户端自定义它们。
我想与具有使用自定义图标或内容从Java创建KMZ文件的经验的人联系。这是我坚持的皱纹:
我手工创建了一堆样式和自定义图标,以便更好地显示客户端数据。最近,我创建了一个Java应用程序,通过自动化KML / KMZ生成,我可以节省大量时间。这些样式直接从示例复制到我的Java代码中(在合法的位置有转义)。 Java代码最初构建了KML,然后我用我的示例中的icons文件夹打包了KML,压缩并保存为KMZ。一切正常。
然后我添加了一个主要基于this example的代码块,并将我的所有图标作为资源添加到jar中。然后我将文件构建为.zip并验证KML和Icon文件(在适当的文件夹中)是否在zip中。他们是。所有人都对世界感到满意。
然后我将输出文件名更改为.kmz而不是.zip,并尝试在Google中运行输出。我的自定义图标都没有加载。 KML工作得很好,点和多边形都有适当的样式颜色,但是中间有X个盒子,好像它不能访问图标。
如果我将输出KMZ重命名为zip,解压缩并在其中运行KML,一切都按预期工作。如果我重新剪辑并重命名为KMZ,它又会被打破。
这是真正的乐趣。如果我将KML从KMZ中取出,使用我工作区资源中的icons文件夹重新打包,保存为KMZ并加载到Google地球,它可以正常工作。
我觉得这告诉我,我的java.util.zip代码以某种方式破坏图像,以至于GE不知道如何处理它们。但我完全感到困惑的是,为什么它们在打包时工作正常,但是当从同一地点重新包装时再次破裂。
有人有什么想法吗?不要发布代码,请提前道歉。如果我们可以稍微缩小问题空间,我会发布我可以发布的内容。
这是我现在可以转录的代码:
//Create new file output based on file-name of previously made KML file (fileOut)
//nameToken exists to pop KML extension off the back end of fileOut.getName()
File fileOut2 = new File(fileOut.getParent(), nameToken2[0] + ".kmz");
FileOutputStream foutstream = new FileOutputStream(fileOut2);
ZipOutputStream zout = new ZipOutputStream(foutstream);
byte[] buffer = new byte[1024];
String[] resourceFiles = {null,"/icons/b-lv.png",...}; //many files listed here
for(int i = 0; i < resourceFiles.length; i++){
//Previously wrote kml file, time to read it in and add to zip
if (i == 0){
FileInputStream fin = new FileInoutStream(fileOut);
zout.putNextEntry(new ZipEntry(fileOut.getName());
int length;
while ((length = fin.read(buffer)) > 0){
zout.write(buffer,0,length);
}
zout.closeEntry();
fin.close();
}
//Read in resource icon files and add to zip
else{
InputStream inStream = this.getClass().getResourceAsStream(resourceFiles[i]);
zout.putNextEntry(new ZipEntry(resourceFiles[i]));
int length;
while((length = inStream.read(buffer)) > 0){
zout.write(buffer,0,length);
}
zout.closeEntry();
inStream.close();
}
}
zout.flush();
zout.close();
foutstream.close();
fileOut.delete(); //Deletes previously made KML file
答案 0 :(得分:5)
这是使用带有根KML文件和图像文件条目的 ZipOutputStream 创建示例KMZ文件的Java代码。如果在添加图像条目之前未正确关闭KML条目,则KMZ文件可能会损坏。
重要提示:您必须确保zip文件条目与KML中的URL引用完全匹配。 zip文件条目应 NOT 以'/'或'../'或'C:/'开头。同样,KML中对KMZ条目的URL / href引用应该是相对的(例如 icons / b-lv.png )到特定的KML文件。
为了减少下面示例中的代码行,Apache commons IOUtils库用于将输入文件复制到KMZ输出流并关闭流。
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import java.io.*;
public class TestKmz {
public static void main(String[] args) throws IOException {
createKMZ();
System.out.println("file out.kmz created");
}
public static void createKMZ() throws IOException {
FileOutputStream fos = new FileOutputStream("out.kmz");
ZipOutputStream zoS = new ZipOutputStream(fos);
ZipEntry ze = new ZipEntry("doc.kml");
zoS.putNextEntry(ze);
PrintStream ps = new PrintStream(zoS);
ps.println("<?xml version='1.0' encoding='UTF-8'?>");
ps.println("<kml xmlns='http://www.opengis.net/kml/2.2'>");
// write out contents of KML file ...
ps.println("<Placemark>");
// add reference to image via inline style
ps.println(" <Style><IconStyle>");
ps.println(" <Icon><href>image.png</href></Icon>");
ps.println(" </IconStyle></Style>");
ps.println("</Placemark>");
ps.println("</kml>");
ps.flush();
zoS.closeEntry(); // close KML entry
// now add image file entry to KMZ
FileInputStream is = null;
try {
is = new FileInputStream("image.png");
ZipEntry zEnt = new ZipEntry("image.png");
zoS.putNextEntry(zEnt);
// copy image input to KMZ output
// write contents to entry within compressed KMZ file
IOUtils.copy(is, zoS);
} finally {
IOUtils.closeQuietly(is);
}
zoS.closeEntry();
zoS.close();
}
}