Search code examples
javaiokmlgoogle-earthkmz

ZipEntry is not storing the images properly


I am trying to create a KMZ file, For that I have passed the images in the program.When I extract the KMZ file it is creating the files folder and it is storing the images into that path, but the images are not viewable, but the last image is viewable but the name and the image is different.

public static void createKMZ(String kmlData)  throws IOException  {
        FileOutputStream fos = new FileOutputStream(KMZ);
        ZipOutputStream zoS = new ZipOutputStream(fos);     
        ZipEntry ze = new ZipEntry(KML);
        zoS.putNextEntry(ze);
        PrintStream ps = new PrintStream(zoS);          
        ps.println(kmlData);
        ps.flush();                 
        zoS.closeEntry();
         // now add image file entry to KMZ
        FileInputStream is = null;
        FileInputStream is1 = null;
        FileInputStream is2 = null;
        FileInputStream is3 = null;
        FileInputStream is4 = null;
        FileInputStream is5 = null;
        FileInputStream is6 = null;
        try {                   
            is  = new FileInputStream("files/grn-pushpin.png");
            is1 = new FileInputStream("files/ltblu-pushpin.png");
            is2 = new FileInputStream("files/pink-pushpin.png");
            is3 = new FileInputStream("files/purple-pushpin.png");
            is4 = new FileInputStream("files/red-pushpin.png");
            is5 = new FileInputStream("files/wht-pushpin.png");
            is6 = new FileInputStream("files/ylw-pushpin.png");
            ZipEntry zEnt = new ZipEntry("files/grn-pushpin.png");
            ZipEntry zEnt1 = new ZipEntry("files/ltblu-pushpin.png");
            ZipEntry zEnt2 = new ZipEntry("files/pink-pushpin.png");
            ZipEntry zEnt3 = new ZipEntry("files/purple-pushpin.png");
            ZipEntry zEnt4 = new ZipEntry("files/red-pushpin.png");
            ZipEntry zEnt5 = new ZipEntry("files/wht-pushpin.png");
            ZipEntry zEnt6 = new ZipEntry("files/ylw-pushpin.png");
            zoS.putNextEntry(zEnt);
            zoS.putNextEntry(zEnt1);
            zoS.putNextEntry(zEnt2);
            zoS.putNextEntry(zEnt3);
            zoS.putNextEntry(zEnt4);
            zoS.putNextEntry(zEnt5);
            zoS.putNextEntry(zEnt6);
            // copy image input to KMZ outputWWW
            // write contents to entry within compressed KMZ file
            IOUtils.copy(is, zoS);
            IOUtils.copy(is1, zoS);
            IOUtils.copy(is2, zoS);
            IOUtils.copy(is3, zoS);
            IOUtils.copy(is4, zoS);
            IOUtils.copy(is5, zoS);
            IOUtils.copy(is6, zoS);
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(is1);
            IOUtils.closeQuietly(is2);
            IOUtils.closeQuietly(is3);
            IOUtils.closeQuietly(is4);
            IOUtils.closeQuietly(is5);
            IOUtils.closeQuietly(is6);
        }
        zoS.closeEntry();
        zoS.close();
    }   

Solution

  • Calling putNextEntry() begins writing a new ZIP file entry, positions the stream to the start of the entry data, and closes the current entry if still active. Therefore, cannot call putNextEntry() without first writing the contents to that entry.

    As defined above, all except the last image file will be a zero byte file.

    Need to reorder the sequence of calls:

    ZipEntry zEnt1 = new ZipEntry();
    zoS.putNextEntry(zEnt1);
    IOUtils.copy(is1, zoS);
    zoS.closeEntry();
    
    ZipEntry zEnt2 = new ZipEntry();
    zoS.putNextEntry(zEnt2);
    IOUtils.copy(is2, zoS);
    zoS.closeEntry();
    ...
    

    Or simplify like this:

    private static void createEntry(String name, ZipOutputStream zoS) throws IOException {
        try(FileInputStream is = new FileInputStream(name)) {
            ZipEntry zEnt = new ZipEntry(name);
            zoS.putNextEntry(zEnt);
            IOUtils.copy(is, zoS);
            zoS.closeEntry();
        }
    }
    
    public static void createKMZ(String kmlData) throws IOException  {
        FileOutputStream fos = new FileOutputStream(KMZ);
        ZipOutputStream zoS = new ZipOutputStream(fos));
        ...
        PrintStream ps = new PrintStream(zoS);          
        ps.println(kmlData);
        ps.flush();
        zoS.closeEntry();
        // now add image file entries to KMZ
        createEntry("files/grn-pushpin.png", zoS);
        createEntry("files/ltblu-pushpin.png", zoS);
        createEntry("files/pink-pushpin.png", zoS);
        createEntry("files/purple-pushpin.png", zoS);
        createEntry("files/red-pushpin.png", zoS);
        createEntry("files/wht-pushpin.png", zoS);
        createEntry("files/ylw-pushpin.png", zoS);
        zoS.close();
    }