Create Zip file for Mac while preserving folder directory structure


Hi,
In my application I am zipping up a directory structure on the server (Linux or PC) and providing a link for the user to download the zip file.  It is important that when the user extract the files the full tree is preserved.  I am using java.util.zip.ZipEntry & java.util.zip.ZipOutputStream to do this.  This works fine with WinZip on PC.   But on Macs (a sizeable chunk of the user), when StuffIt extract the file, the directory names get merged as part of the file name.  So I get only a single folder with lots of files with long names (e.g. "D:\xxx\yyy\dd\hello.txt").  When I use tar and gzip on unix to create the file this does not happen, folder structures are preserved.  But when I use java this happens.  How do I get around this?  I am new to creating zip files with java so please be detailed in your explaination.

I am also looking for ways to creat zip file with "relative" path rather than "absolute" but haven't figure that out yet.  My code is running under Tomcat 4.1.  Could this be my problem?

 Here's the main part of my code:


  public boolean executeZip() throws
      IOException {

    String inputFiles = "D:\\download\\InDir\\08_24_ID5551212";
    String outZipFileName = "TestZip.zip";
    String outputZipFilePath = "D:\\download\\OutDir" + "\\" + outZipFileName;
   
    System.out.println("Zipping files in " + inputFiles);
   

    try {
      System.out.println("Output file path:" + outputZipFilePath);
      //create a ZipOutputStream to zip the data to
      ZipOutputStream zos = new
          ZipOutputStream(new FileOutputStream(outputZipFilePath));
     
      zipDir(inputFiles, zos);
      //close the stream
      zos.close();
      File file = new File(outputZipFilePath);

      // Get the number of bytes in the file
      outputZipFileSize = file.length() / 1024;

    }
    catch (InterruptedException e) {
      setRunning(false);
      return false;
    }
    catch (Exception e) {
      //handle exception
      System.out.println(e);
      return false;
    }

    return true;
  }

  public void zipDir(String dir2zip, ZipOutputStream zos) throws Exception {

    //create a new File object based on the directory we have to zip File
    File zipDir = new File(dir2zip);
    //get a listing of the directory content
    String[] dirList = zipDir.list();
    byte[] readBuffer = new byte[2156];
    int bytesIn = 0;
    //loop through dirList, and zip the files
    for (int i = 0; i < dirList.length; i++) {
      File f = new File(zipDir, dirList[i]);
      if (f.isDirectory()) {
        //if the File object is a directory, call this
        //function again to add its content recursively
        String filePath = f.getPath();
        zipDir(filePath, zos);
        //loop again
        continue;
      }
      //if we reached here, the File object f was not a directory
      //create a FileInputStream on top of f
      FileInputStream fis = new FileInputStream(f);
      //create a new zip entry
      ZipEntry anEntry = new ZipEntry(f.getPath());
      //place the zip entry in the ZipOutputStream object
      zos.putNextEntry(anEntry);
      //now write the content of the file to the ZipOutputStream
      while ( (bytesIn = fis.read(readBuffer)) != -1) {
        zos.write(readBuffer, 0, bytesIn);
      }
      //close the Stream
      fis.close();
    }
  }
tangowayneAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Tommy BraasCommented:
You can truncate the path part of the ZipEntry. I.e., the path the ZipEntry has is the path with which it is stored in the Zip file. Before creating the ZipEntry, substring the file system path to something appropriate for your application.

\t
0
Tommy BraasCommented:
Also, it would be a good idea to change all back slashes to forward slashes. Forward slashes are handled correctly on all platforms.

\t
0
WebstormCommented:
Hi tangowayne,

As orangehead911 said :
>> Also, it would be a good idea to change all back slashes to forward slashes.
but the actual reason is zip files only supports '/' as file separator.

>> ZipEntry anEntry = new ZipEntry(f.getPath());
maybe you don't want the fullpath in the zip file, but a relative one :
String fpath=f.getPath();
if (fpath.startsWith(abs_base_dir)) fpath=fpath.substring(abs_base_dir.length());
ZipEntry anEntry = new ZipEntry(fpath);




0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

tangowayneAuthor Commented:
Thanks Webstorm and orangehead911.  It makes sense to me now and it's working beautifully.

0
Tommy BraasCommented:
=-)
0
WebstormCommented:
:-)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.