无法使用java.util.zip创建KMZ文件

时间:2012-10-05 15:17:27

标签: java zip kml google-earth kmz

所以,我过去已经制作了一些样本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

1 个答案:

答案 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();
    }   
}