Avatar billede heine112 Nybegynder
04. februar 2006 - 16:50 Der er 22 kommentarer og
2 løsninger

Zip og Unzip

Har du en eller to simple java-klasser, som kan:

1) Zippe en folder
2) Unzippe en folder.

Jeg forstiller mig lidt i denne stil: java Zip c:\temp\katalog

og: java Unzip c:\temp\katalog

/Heine
Avatar billede mikkelbm Nybegynder
04. februar 2006 - 16:54 #1
Jeg har en lille simpel klasse liggende:

package dk.bluetone.util;

import java.io.*;
import java.util.*;
import java.util.zip.*;

/**
* Nem tilgang til at zippe nogle filer, samt unzippe dem.
*
* @author Bluetone
* @version 1.0
*/
public class ZipManager
{
  static final int BUFFER = 2048;

  public static boolean zipFiles(File[] files, File zipFile)
  {
    if (files.length < 1)
      return false;
    try
    {
      BufferedInputStream origin = null;
      FileOutputStream dest = new FileOutputStream(zipFile);
      ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
      //out.setMethod(ZipOutputStream.DEFLATED);
      byte data[] = new byte[BUFFER];

      for (int i = 0; i < files.length; i++)
      {
        // Metoden kan i øjeblikket ikke håndtere directories...
        if (!files[i].isDirectory())
        {
          FileInputStream fi = new FileInputStream(files[i]);
          origin = new BufferedInputStream(fi, BUFFER);
          ZipEntry entry = new ZipEntry(files[i].getName());
          out.putNextEntry(entry);
          int count;
          while ( (count = origin.read(data, 0, BUFFER)) != -1)
          {
            out.write(data, 0, count);
          }
          origin.close();
        }
      }
      out.flush();
      out.close();

      return true;
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }
  }

  public static boolean unZip(File zipFile, File path)
  {
    try
    {
      BufferedOutputStream dest = null;
      BufferedInputStream is = null;
      ZipEntry entry;
      ZipFile zipfile = new ZipFile(zipFile);
      Enumeration e = zipfile.entries();

      while (e.hasMoreElements())
      {
        entry = (ZipEntry) e.nextElement();
        System.out.println("Extracting: " + entry);
        is = new BufferedInputStream(zipfile.getInputStream(entry));
        int count;
        byte data[] = new byte[BUFFER];

        if (!path.exists())
          path.mkdir();

        String p = path.getAbsolutePath();
        if (!p.endsWith("\\"))
          p += "\\";

        FileOutputStream fos = new FileOutputStream(p + entry.getName());
        dest = new BufferedOutputStream(fos, BUFFER);

        while ( (count = is.read(data, 0, BUFFER)) != -1)
        {
          dest.write(data, 0, count);
        }
        dest.flush();
        dest.close();
        is.close();
      }
      return true;
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }
  }

}
Avatar billede heine112 Nybegynder
04. februar 2006 - 17:13 #2
Hej
Kan programme tage subdirectories ? Du skriver:Metoden kan i øjeblikket ikke håndtere directories...
Avatar billede mikkelbm Nybegynder
04. februar 2006 - 17:15 #3
Nej, den tager i øjeblikket kun filer.
Avatar billede mikkelbm Nybegynder
04. februar 2006 - 17:16 #4
Avatar billede heine112 Nybegynder
04. februar 2006 - 17:59 #5
Hej
Der er vist lidt knas i "p + entry.getName()" Jeg unzipper filen
curDir.zip til c:\temp\testen333
( se linien zipmanager.unZip(new File("curDir.zip"),new File("c:\\temp\\testen333)"));    )
og får fejlen:

Extracting: c:\temp\zip\COPYING
c:\temp\hesten333)\c:\temp\zip\COPYING
java.io.FileNotFoundException: c:\temp\testen333)\c:\temp\zip\COPYING (Syntaksen
i filnavnet, mappen eller diskenhedsnavnet er forkert)
        at java.io.FileOutputStream.open(Native Method)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
        at ZipManager.unZip(ZipManager.java:41)
        at ZipManager.main(ZipManager.java:138)
Avatar billede mikkelbm Nybegynder
04. februar 2006 - 19:18 #6
Mon ikke det er her:

"c:\\temp\\testen333)"

Den sidste parantes skal vel ikke være der? :)
Avatar billede heine112 Nybegynder
04. februar 2006 - 19:42 #7
Du har ret i, at der er en fejl ")" - men den vil gemme filen som
c:\temp\hesten333)\c:\temp\zip\COPYING

altså med dobbelt "c:\"
Avatar billede mikkelbm Nybegynder
04. februar 2006 - 19:44 #8
Ja, men det er nok på grund at den parantes. Har du prøvet at fjerne den?
Avatar billede heine112 Nybegynder
04. februar 2006 - 20:05 #9
Hej
Jeg har rettet i klassen (så den hedder UnZip).

Jeg har en eksisterende zipfil aaa.zip i c:\temp - den vil jeg gerne pakke ud.
Og jeg vil gerne pakke den ud i c:\temp\nydir. Dvs jeg vil have c:\temp\nydir fyldt med filer og kataloger fra zip-filen aaa.zip.

Jeg anvender:
    File zipfil = new File("c:\\temp\\aaa.zip");
    File dir =  new File("c:\\temp\nydir");

Måske bruges programmet på en anden måde ?

Jeg får output og fejlen:
Extracting: mimetype
c:\temp\nydir\mimetype
Extracting: Configurations2/
c:\temp\nydir\Configurations2/
Extracting: content.xml
c:\temp\nydir\content.xml
Extracting: styles.xml
c:\temp\nydir\styles.xml
Extracting: meta.xml
c:\temp\nydir\meta.xml
Extracting: Thumbnails/thumbnail.png
c:\temp\nydir\Thumbnails/thumbnail.png
java.io.FileNotFoundException: c:\temp\nydir\Thumbnails\thumbnail.png (Den angiv
ne sti blev ikke fundet)
        at java.io.FileOutputStream.open(Native Method)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
        at UnZip.unZip(UnZip.java:53)
        at UnZip.main(UnZip.java:18)


Her er programmet lettere modificeret:
public class UnZip{

  public static void main(String[] a) {
    UnZip u = new UnZip();   
    File zipfil = new File("c:/temp//aaa.zip");
    File dir =  new File("c:/temp//nydir");
    u.unZip(zipfil,dir); 
  }
 


  static final int BUFFER = 2048;


  public static boolean unZip(File zipFile, File path)
  {
    try
    {
      BufferedOutputStream dest = null;
      BufferedInputStream is = null;
      ZipEntry entry;
      ZipFile zipfile = new ZipFile(zipFile);
      Enumeration e = zipfile.entries();

      while (e.hasMoreElements())
      {
        entry = (ZipEntry) e.nextElement();
        System.out.println("Extracting: " + entry);
        is = new BufferedInputStream(zipfile.getInputStream(entry));
        int count;
        byte data[] = new byte[BUFFER];

        if (!path.exists())
          path.mkdir();

        String p = path.getAbsolutePath();
        if (!p.endsWith("\\"))
          p += "\\";

        System.out.println(p + entry.getName());

        FileOutputStream fos = new FileOutputStream(p + entry.getName());
        dest = new BufferedOutputStream(fos, BUFFER);

        while ( (count = is.read(data, 0, BUFFER)) != -1)
        {
          dest.write(data, 0, count);
        }
        dest.flush();
        dest.close();
        is.close();
      }
      return true;
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }
  }

}
Avatar billede mikkelbm Nybegynder
04. februar 2006 - 20:12 #10
Det er nok fordi, at den metode ikke kan håndtere subdirectories. Jeg har desværre ikke tid til at kigge mere på det i aften.
Avatar billede _carsten Nybegynder
06. februar 2006 - 17:05 #11
Har lige siddet og leget lidt med den her, ved ikke om det lige er det, men jeg  synes nedenstående stort set fungerer a la WinZip - eller hva ?????



public class NewMain {
    public NewMain() {
    }

    public static void main(String[] args) {
        File[] f = new File[]{new File("C:\\DIR_HVORFRA_FILER_SKAL_ZIPPES\\")};
        File zip = new File("C:\\ZIP.zip");
        ZipManager.zipFiles(f, zip);
       
        ZipManager.unZipFiles(zip, new File("C:\\test\\udpak\\"));
    }
}


import java.io.*;
import java.util.*;
import java.util.zip.*;

public class ZipManager{
  static final int BUFFER = 2048;

  public static boolean zipFiles(File[] files, File zipFile) {
      if (files == null || zipFile == null || files.length < 1)
          return false;
     
      try{
          FileOutputStream fos = new FileOutputStream(zipFile);
          ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
         
          String b = findBase(files);

          for (int i = 0; i < files.length; i++) {
              if( !filesToZip(files[i], zos, b) ){
                  return false;
              }
          }
          zos.flush();
          zos.close();
      } catch (Exception e) {
          e.printStackTrace();
          return false;
      }
     
      return true;
  }

  public static boolean unZipFiles(File zipFile, File unZipToPath) {
      try {
          String separator = System.getProperty("file.separator");
          BufferedOutputStream dest = null;
          BufferedInputStream is = null;
          ZipEntry entry;
          ZipFile zipfile = new ZipFile(zipFile);
          Enumeration e = zipfile.entries();

          if (!unZipToPath.exists())
              unZipToPath.mkdirs();

          while (e.hasMoreElements()) {
              entry = (ZipEntry) e.nextElement();
              System.out.println("Extract to base: " + unZipToPath + separator + "  file: " + entry);
              is = new BufferedInputStream(zipfile.getInputStream(entry));
              int count;
              byte data[] = new byte[BUFFER];
             
              String fileEntry = entry.toString();
              int entryLength = fileEntry.lastIndexOf( separator );
             
              if (entryLength > 0){
                  File f = new File(unZipToPath + separator + fileEntry.substring(0, entryLength));
                  if(!f.isDirectory())
                      f.mkdirs();
              }

              FileOutputStream fos = new FileOutputStream(unZipToPath + separator + entry.getName());
              dest = new BufferedOutputStream(fos, BUFFER);
             
              while ( (count = is.read(data, 0, BUFFER)) != -1) {
                  dest.write(data, 0, count);
              }
              dest.flush();
              dest.close();
              is.close();
          }
          return true;
      } catch (Exception e) {
          e.printStackTrace();
          return false;
      }
  }

  private static String findBase(File[] file){
      String f = "", base = "";
      String separator = System.getProperty("file.separator");
     
      int index = -1;
      int oldIndex = 10000;
     
      for (int i = 0; i < file.length; i++) {
          f = file[i].getPath();
          index = f.lastIndexOf( separator );
          if(index < oldIndex && index >= 0){
              oldIndex = index;
              base = f.substring(0, f.length());
          }
      }
     
      if(!base.endsWith( separator ))
          base += separator;
     
      return base;
  }
 
  private static boolean filesToZip(File path, ZipOutputStream z, String base){
        File[] dir;

        dir = path.listFiles();
       
        if(dir == null || dir.length == 0)
            return false;
       
        FileInputStream fis;
       
        for(int x=0;x < dir.length;x++) {
            if(dir[x].isFile()){
                try {
                    fis = new FileInputStream(dir[x]);
                    String b = dir[x].getPath();
                   
                    String entryToAdd = b.substring(base.length(), b.length());

                    ZipEntry anEntry = new ZipEntry( entryToAdd );
                    z.putNextEntry(anEntry);

                    int bytesRead = 0;
                    byte[] readBuffer = new byte[2048];

                    while((bytesRead = fis.read(readBuffer)) != -1) {
                        z.write(readBuffer, 0, bytesRead);
                    }

                    z.closeEntry();
                    fis.close();
                   
                } catch (FileNotFoundException ex) {
                    ex.printStackTrace();
                    return false;
                } catch (IOException ex) {
                    ex.printStackTrace();
                    return false;
                }
            }
            else
                filesToZip(dir[x], z, base);
        }
        return true;
    }
}
Avatar billede mikkelbm Nybegynder
18. februar 2006 - 13:21 #12
Kommet videre?
Avatar billede heine112 Nybegynder
24. marts 2006 - 13:23 #13
Hej
Deltagerne må gerne smide et svar. Der kom nogle andre problemer, så jeg skifte fokus.
Avatar billede mikkelbm Nybegynder
24. marts 2006 - 13:41 #14
svar...
Avatar billede _carsten Nybegynder
24. marts 2006 - 15:47 #15
Det være hermed gjort
Avatar billede rmjdk Nybegynder
02. september 2007 - 00:50 #16
For lige at hive en gammel tråd op, så har jeg forsøgt mig med _carstens eksempel fra 06/02 og den vil  - desværre - ikke udpakke en zip fil hvis der er dirs inden i, hvad kan være galt ?

Extract to base: N:\testWin\  file: app_test/app_test/
java.io.FileNotFoundException: N:\testWin\app_test\app_test (The system cannot find the path specified)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
    at ziptest.ZipHelper.unZipFiles(ZipHelper.java:90)
    at ziptest.UnpackTester.main(UnpackTester.java:22)

får jeg at vide...

på forhånd tak!
Avatar billede _carsten Nybegynder
02. september 2007 - 10:19 #17
Sorry - det er mig som har lavet en bøf!

Udskift metoden unZipFiles med nedenstående

  public static boolean unZipFiles(File zipFile, File unZipToPath) {
      try {
          String separator = System.getProperty("file.separator");
          BufferedOutputStream dest = null;
          BufferedInputStream is = null;
          ZipEntry entry;
          ZipFile zipfile = new ZipFile(zipFile);
          Enumeration e = zipfile.entries();

          if (!unZipToPath.exists())
              unZipToPath.mkdirs();

          while (e.hasMoreElements()) {
              File f;
              entry = (ZipEntry) e.nextElement();
             
              if(entry.isDirectory()){
                  new File(unZipToPath + separator + entry.toString()).mkdir();
              }
              else{
                  is = new BufferedInputStream(zipfile.getInputStream(entry));
                  int count;
                  byte data[] = new byte[BUFFER];
             
                  FileOutputStream fos = new FileOutputStream(unZipToPath + separator + entry.getName());
                  dest = new BufferedOutputStream(fos, BUFFER);

                  while ( (count = is.read(data, 0, BUFFER)) != -1) {
                      dest.write(data, 0, count);
                  }
                  dest.flush();
                  dest.close();
                  is.close();
              }
          }
          return true;
      } catch (Exception e) {
          e.printStackTrace();
          return false;
      }
  }
Avatar billede rmjdk Nybegynder
02. september 2007 - 11:39 #18
Hej carsten!

For det første tak for det hurtige svar!
Men den virker stadig ikke helt, den vil stadig kun pakke zip filer ud som indeholder filer, hvis en zip indeholder dirs får jeg enten bare en FileNotFoundException eller den eksekverer færdig og jeg får et tomt dir.

Ydermere får jeg en Warning(74,14): variable f declared but never read (i while(e.hasMoreElements())

igen - på forhånd tak!
Avatar billede _carsten Nybegynder
02. september 2007 - 18:10 #19
Ja det er rigtigt nok, jeg erklærede den, men valgte ikke at bruge den

while (e.hasMoreElements()) {
-->  File f;  // Fjern denne linie

Det andet borer jeg i lidt senere  på aftenen !
Avatar billede _carsten Nybegynder
02. september 2007 - 19:37 #20
Jeg forstår det ikke - kan ikke få den til at lave fejl !

Prøv at downloade jdk118-doc-2.zip her:
http://www.it.kau.se/~eivind/oom/downloads/jdk118.zip/download-jdk118-doc.html

og pak den ud.

Jeg har prøvet med mange forskellige zip-filer og jeg kan ikke få den til at lave nogen fejl
Avatar billede rmjdk Nybegynder
05. september 2007 - 12:02 #21
Hej Carsten!

Prøv at udpakke denne (virker med winzip).

http://a.guu.dk/app_test.zip

Jeg får følgende:

java.io.FileNotFoundException: N:\aupod\app_test\build.xml (The system cannot find the path specified)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
    at ziptest.ZipHelper.unZipFiles(ZipHelper.java:96)
    at ziptest.UnpackTester.main(UnpackTester.java:32)
Process exited with exit code 0.

Igen - på forhånd tak!
Avatar billede rmjdk Nybegynder
05. september 2007 - 12:41 #22
Jeg har også præsteret at få en:

processing: AERx© iDMS ADA 2006 Med Lounge.ppt
java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:134)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
    at ziptest.ZipHelper.unZipFiles(ZipHelper.java:100)
    at ziptest.UnpackTester.main(UnpackTester.java:32)

processing: <- er en sop i starten af while løkken for at se hvilken fil den er igang med.
Avatar billede _carsten Nybegynder
05. september 2007 - 20:50 #23
Du har ret, det er FileOutputStream som fejler hvis der mangler et dir!

Så tror jeg vi er der med denne


  public static boolean unZipFiles(File zipFile, File unZipToPath) {
      try {
          String separator = System.getProperty("file.separator");
          BufferedOutputStream dest = null;
          BufferedInputStream is = null;
          ZipEntry entry;
          ZipFile zipfile = new ZipFile(zipFile);
          Enumeration e = zipfile.entries();

          if (!unZipToPath.exists())
              unZipToPath.mkdirs();

          while (e.hasMoreElements()) {
              entry = (ZipEntry) e.nextElement();
             
              if(entry.isDirectory()){
                  File f = new File(unZipToPath + separator + entry.toString());
                  if( !f.exists())
                      f.mkdir();
              }
              else{
                  int x = entry.toString().lastIndexOf("/");
         
                  if(x > 0 ){
                      String p = unZipToPath + separator + entry.toString().substring(0,x);
                      File f = new File( p );
                      if( !f.exists())
                          f.mkdir();
                  }
                 
                  is = new BufferedInputStream(zipfile.getInputStream(entry));
                  int count;
                  byte data[] = new byte[BUFFER];
             
                  String path = unZipToPath + separator + entry.getName().replaceAll("/", "\\\\");

                  FileOutputStream fos = new FileOutputStream(new File( path));
                  dest = new BufferedOutputStream(fos, BUFFER);

                  while ( (count = is.read(data, 0, BUFFER)) != -1) {
                      dest.write(data, 0, count);
                  }
                  dest.flush();
                  dest.close();
                  is.close();
                 
              }
          }
          return true;
      } catch (Exception e) {
          e.printStackTrace();
          return false;
      }
  }
Avatar billede rmjdk Nybegynder
05. september 2007 - 21:19 #24
Hej carsten!

Det ser ud som om det det funker nu! jeg bukker og takker mange gange!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester