title: Java Zip File Extraction
body: <p>I have a GTFS schedule manager which automatically downloads a zipped file from a specified provider URL and extracts files from it on the fly to a specified folder. So at the end of this process the folder contains just the extracted files and not the zipped file itself.</p>
  
  <p>This has up to now always worked worked but with</p>
  
  <p><a href="http://mta.maryland.gov/_googletransit/latest/google_transit.zip" rel="nofollow noreferrer">http://mta.maryland.gov/_googletransit/latest/google_transit.zip</a></p>
  
  <p>it does not work for some reason. When I go to get the first zip entry from the stream it is null.  I can however manually download the zipped file to a local folder, change the URL in my java application to it and it extracts fine. It is just the extraction on the fly that does not work.</p>
  
  <p>This is demonstrated by running the code below as it is: you will see the failure. If you then download the zipped file manually to the "feeds" folder and swap around the commented "extractFilesFromFeed.extract" lines in main below the extraction works.</p>
  
  <p>Question is if there a change I can make below so that this particular URL can be extracted on the fly ?</p>
  
  <p>===</p>
  
  <pre><code>import java.io.File;
  import java.io.FileOutputStream;
  import java.net.URL;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipInputStream;
  
  public class ExtractFilesFromFeed {
  
    private Logger logger = Logger.getLogger("");
  
    public void extract(String feedLocation, String feedFolder) throws Exception  {
      if (feedLocation == null || feedLocation.length() == 0) {
        String tmp = "Invalid feed location specified for GTFS schedule file extraction";
        throw new Exception(tmp);
      }
      else if (feedFolder == null || feedFolder.length() == 0) {
        String tmp = "Invalid feed folder specified for GTFS schedule file extraction";
        throw new Exception(tmp);
      }
      else {
        logger.log(Level.INFO, String.format("Extracting GTFS schedule files from %s to %s", 
            feedLocation, feedFolder));
      }
  
      URL url;
      if (feedLocation.startsWith("http")) {
        url = new URL(feedLocation);
      }
      else {
        url = new File(feedLocation).toURI().toURL();
      }
  
      File dir = new File(feedFolder);
      if(!dir.exists()){
        dir.mkdir();
      }
  
      byte[] buffer = new byte[8192];
      ZipInputStream zis = new ZipInputStream(url.openStream());
      ZipEntry ze = zis.getNextEntry();
  
      if (ze == null) {
        logger.log(Level.WARNING, "Unable to get first entry from zip file, aborting download");
        zis.close();
        throw new Exception(String.format("Unable to get first entry from zip file %s", feedLocation));
      }
  
      while (ze != null){
        String zipFileName = ze.getName();
        if (ze.isDirectory()) {
          dir = new File(feedFolder + "/" + zipFileName);
          if(!dir.exists()){
            dir.mkdir();
          }
        }
        else {
          FileOutputStream fos = new FileOutputStream(feedFolder + File.separator + zipFileName);
          int len;
          while ((len = zis.read(buffer)) &gt; 0) {
            fos.write(buffer, 0, len);
          }
          fos.close();   
        }
        ze = zis.getNextEntry();
      }
      zis.close();
    }
  
    public static void main(String[] args) throws Exception {
      ExtractFilesFromFeed extractFilesFromFeed = new ExtractFilesFromFeed();
      extractFilesFromFeed.extract("http://mta.maryland.gov/_googletransit/latest/google_transit.zip", "feeds");
      //extractFilesFromFeed.extract("feeds/google_transit.zip", "feeds");
    }
  }
  </code></pre>