Create Zip file for Mac while preserving folder directory structure

Posted on 2004-10-26
Last Modified: 2008-02-01

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 & 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 = "";
    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
      File file = new File(outputZipFilePath);

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

    catch (InterruptedException e) {
      return false;
    catch (Exception e) {
      //handle exception
      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
      //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
      //now write the content of the file to the ZipOutputStream
      while ( (bytesIn = != -1) {
        zos.write(readBuffer, 0, bytesIn);
      //close the Stream
Question by:tangowayne
    LVL 14

    Expert Comment

    by:Tommy Braas
    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.

    LVL 14

    Assisted Solution

    by:Tommy Braas
    Also, it would be a good idea to change all back slashes to forward slashes. Forward slashes are handled correctly on all platforms.

    LVL 13

    Accepted Solution

    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);


    Author Comment

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

    LVL 14

    Expert Comment

    by:Tommy Braas
    LVL 13

    Expert Comment


    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    What Should I Do With This Threat Intelligence?

    Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

    Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
    Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
    Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
    This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

    931 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    22 Experts available now in Live!

    Get 1:1 Help Now