Search code examples
javaapacheftp-clientftp4j

Java GZipInputStream unexpected end of ZLib input stream


For reference, here is the complete error I am getting:

    java.io.EOFException: Unexpected end of ZLIB input stream
at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:240)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:117)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at com.genomedownloader.Main.FTPGet(Main.java:245)
at com.genomedownloader.Main.access$400(Main.java:28)
at com.genomedownloader.Main$1.call(Main.java:494)
at com.genomedownloader.Main$1.call(Main.java:468)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:

I just switched my program from using FTP4J as a Java FTP client to Apache FTPClient. I tweaked my download code so that Apache would work, now I get this exception when I try to unzip the *.gz files the program downloads. Here is the relevant code:

 package com.test;

 import org.apache.commons.net.ftp.FTPClient;

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

 public class Main {
public static void main(String[] args) throws IOException {
    FTPClient client;
    client = new FTPClient();
    client.connect("ftp.ncbi.nlm.nih.gov");
    client.login("anonymous", "abc123");
    client.setControlKeepAliveTimeout(300 * 60000);
    client.changeWorkingDirectory("/genomes/all/GCF/000/334/875/GCF_000334875.1_ASM33487v1");
    client.retrieveFile("GCF_000334875.1_ASM33487v1_genomic.fna.gz", new BufferedOutputStream(new FileOutputStream(new File(System.getProperty("user.dir") + "\\GenomicFNA.gz"))));
    GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream(System.getProperty("user.dir") + "\\GenomicFNA.gz"));
    OutputStream out = new FileOutputStream(System.getProperty("user.dir") + "\\GenomicFNA.fsa");
    byte[] buf = new byte[1024];
    int len;
    while ((len = gzipInputStream.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    gzipInputStream.close();
    out.close();
    client.logout();
    client.disconnect();
}
}

What I can't figure out for the life of me is WHY the code works with FTP4J but then fails with Apache, despite the code using nothing from Apache nor FTP4j libraries... Run the above code with Apache commons net, and it should work. (Work as in give the error at the top)


Solution

  • Change the BufferedOutputStream to separate declaration, and change the FileOutputStream likewise, then flush and close both of them before the GZip declaration. Completed code:

      package com.test;
    
       import org.apache.commons.net.ftp.FTPClient;
    
      import java.io.*;
      import java.util.zip.GZIPInputStream;
    
    public class Main {
    public static void main(String[] args) throws IOException {
        BufferedOutputStream streamy;
        FileOutputStream stream;
        FTPClient client;
        client = new FTPClient();
        client.connect("ftp.ncbi.nlm.nih.gov");
        client.login("anonymous", "abc123");
        client.setControlKeepAliveTimeout(300 * 60000);
        client.changeWorkingDirectory("/genomes/all/GCF/000/334/875/GCF_000334875.1_ASM33487v1");
        client.retrieveFile("GCF_000334875.1_ASM33487v1_genomic.fna.gz", streamy = new BufferedOutputStream(stream = new FileOutputStream(new File(System.getProperty("user.dir") + "\\GenomicFNA.gz"))));
        stream.flush();
        streamy.flush();
        stream.close();
        streamy.close();
        client.logout();
        client.disconnect();
        GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream(System.getProperty("user.dir") + "\\GenomicFNA.gz"));
        OutputStream out = new FileOutputStream(System.getProperty("user.dir") + "\\GenomicFNA.fsa");
        byte[] buf = new byte[1024];
        int len;
        while ((len = gzipInputStream.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        gzipInputStream.close();
        out.close();
    
    }
    }