我在一个项目上使用JAK已有一年多了。我用它来创建KML,然后将其编组为普通的KML(而不是KMZ)。我创建了一个单独的实用程序类,该实用程序类使用Java
SE“
Zip”类手动创建KMZ。它工作正常。KMZ只不过是一个.zip存档,其中仅包含一个.kml文件和0个或多个资源文件(例如图像等)。唯一的区别是,在输出文件时,将其命名为.kmz而不是.zip。在KML文档
<Style>定义中,请使用与KML文档本身有关的路径来引用您的资源文件。KML文件被认为位于KMZ归档文件的“根目录”中。如果您的资源文件也位于KMZ(.zip)的根目录中,则您不需要路径,只需文件名。
编辑: 我实际上忘记Kml
了在压缩文件之前删除了将JAK
对象编组到文件的中间步骤。我下面的实用程序方法会将Kml
对象直接封送到ZipOutputStream
。
这是我创建的实用程序类,用于执行我所描述的事情。我将其发布在这里,希望其他人发布仅使用JAK的替代解决方案,以便将来我可以停用此代码。目前,这将为您完成工作。
注意:如果不使用slf4j,Apache Commons Lang或Commons I /
O,则只需对代码进行一些调整即可用您自己的代码删除/替换这些位。 显然,此代码需要JAK库。
package com.jimtough;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.Collections;import java.util.List;import java.util.zip.ZipEntry;import java.util.zip.ZipOutputStream;import org.apache.commons.io.IOUtils;import org.apache.commons.lang.Validate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import de.micromata.opengis.kml.v_2_2_0.Kml;public final class KMZPackager { private final static Logger logger = LoggerFactory.getLogger(KMZPackager.class); public static abstract class DataSource { protected String archivedFileName; public abstract void writeToStream(ZipOutputStream zipOutputStream) throws IOException; } public static final class FileDataSource extends DataSource { private File sourceFile; public FileDataSource( File sourceFile, String archivedFileName) throws IllegalArgumentException { Validate.notNull(sourceFile); Validate.notEmpty(archivedFileName); this.sourceFile = sourceFile; this.archivedFileName = archivedFileName; } @Override public void writeToStream(ZipOutputStream zipOutputStream) throws IOException { Validate.notNull(zipOutputStream); // Check that the file exists, and throw an appropriate exception // before reading it if (!sourceFile.exists()) { throw new IllegalArgumentException( "File referenced in parameter [" + sourceFile.getAbsolutePath() + "] does not exist"); } FileInputStream fis = new FileInputStream(sourceFile); if (logger.isDebugEnabled()) { logger.debug("Adding file to KMZ archive" + " | archive name: " + archivedFileName + " | original name: " + sourceFile.getCanonicalPath()); } // Mark the start of this new file in the ZIP stream ZipEntry entry = new ZipEntry(archivedFileName); zipOutputStream.putNextEntry(entry); // Use the Apache commons-io library to do a buffered // stream-to-stream copy try { IOUtils.copy(fis, zipOutputStream); } finally { fis.close(); } } } public static final class KMLDataSource extends DataSource { private Kml kml; public KMLDataSource( Kml kml, String archivedFileName) throws IllegalArgumentException { Validate.notNull(kml); Validate.notEmpty(archivedFileName); this.kml = kml; this.archivedFileName = archivedFileName; } @Override public void writeToStream(ZipOutputStream zipOutputStream) throws IOException { Validate.notNull(zipOutputStream); // Mark the start of this new file in the ZIP stream ZipEntry entry = new ZipEntry(archivedFileName); zipOutputStream.putNextEntry(entry); // Marshal the Kml object directly to the ZipOutputStream if (logger.isDebugEnabled()) { logger.debug("Marshalling KML to KMZ archive" + " | archive name: " + archivedFileName); } kml.marshal(zipOutputStream);} } public static final class StreamDataSource extends DataSource { private InputStream inputStream; public StreamDataSource( InputStream inputStream, String archivedFileName) throws IllegalArgumentException { Validate.notNull(inputStream); Validate.notEmpty(archivedFileName); this.inputStream = inputStream; this.archivedFileName = archivedFileName; } @Override public void writeToStream(ZipOutputStream zipOutputStream) throws IOException { Validate.notNull(zipOutputStream); // Mark the start of this new file in the ZIP stream ZipEntry entry = new ZipEntry(archivedFileName); zipOutputStream.putNextEntry(entry); // Use the Apache commons-io library to do a buffered // stream-to-stream copy if (logger.isDebugEnabled()) { logger.debug("Copying KML from stream to KMZ archive" + " | archive name: " + archivedFileName); } try { IOUtils.copy(inputStream, zipOutputStream); } finally { inputStream.close(); } } } public void packageAsKMZ( OutputStream os, DataSource kmlDataSource, List<FileDataSource> supplementaryFileList) throws RuntimeException { ZipOutputStream zipOutputStream = null; boolean isExceptionThrown = false; Exception caughtException = null; List<FileDataSource> supplFileList = supplementaryFileList; try { Validate.notNull(os, "os parameter cannot be null"); Validate.notNull(kmlDataSource, "kmlFileDataSource parameter cannot be null"); // Treat a null parameter just like an empty list (which is OK) if (supplFileList == null) { supplFileList = Collections.emptyList(); } if (logger.isDebugEnabled()) { logger.debug( "Creating KMZ archive" + " | supplementary files: " + supplFileList.size()); } // Create a buffered output stream for the new KMZ file zipOutputStream = new ZipOutputStream(new BufferedOutputStream(os)); Validate.isTrue( kmlDataSource.archivedFileName.endsWith(".kml"), "KML archived file name must end with .kml"); kmlDataSource.writeToStream(zipOutputStream); // Now process the list of supplementary files if (logger.isDebugEnabled()) { logger.debug("Adding supplementary files to KMZ archive" + " | archive name: "); } for (FileDataSource ds : supplFileList) { Validate.isTrue( !ds.archivedFileName.endsWith(".kml"), "Not legal to include .kml files in supplementary list"); ds.writeToStream(zipOutputStream); } // Close the output stream to complete the ZIP creation zipOutputStream.flush(); zipOutputStream.close(); logger.info("KMZ archive created successfully"); } catch (IOException e) { isExceptionThrown = true; caughtException = e; logger.error("IOException while creating ZIP stream"); } catch (IllegalArgumentException e) { isExceptionThrown = true; caughtException = e; } catch (RuntimeException e) { isExceptionThrown = true; caughtException = e; } finally { if (isExceptionThrown) { try { if (zipOutputStream != null) { zipOutputStream.close(); } } catch (IOException ioe) { // Don't care } throw new RuntimeException(caughtException); } } }}


