tags:

views:

69

answers:

5

I'm reading a bunch of files from an FTP. Then I need to unzip those files and write them to a fileshare.

I don't want to write the files first and then read them back and unzip them. I want to do it all in one go. Is that possible?

This is my code

FTPClient fileclient = new FTPClient();
..

ByteArrayOutputStream out = new ByteArrayOutputStream();
fileclient.retrieveFile(filename, out);

??????? //How do I get my out-stream into a File-object? 

File file = new File(?);

ZipFile zipFile = new ZipFile(file,ZipFile.OPEN_READ);

Any ideas?

+1  A: 

Well, you could just create a FileOutputStream and then write the data from that:

FileOutputStream fos = new FileOutputStream(filename);
try {
  out.writeTo(out);
} finally {
  fos.close();
}

Then just create the File object:

File file = new File(filename);

You need to understand that a File object doesn't represent any real data on disk - it's just a filename, effectively. The file doesn't even have to exist. If you want to actually write data, that's what FileOutputStream is for.

EDIT: I've just spotted that you didn't want to write the data out first - but that's what you've got to do, if you're going to pass the file to something that expects a genuine file with data in.

If you don't want to do that, you'll have to use a different API which doesn't expect a file to exist... as per Qwerky's answer.

Jon Skeet
+4  A: 

You should use a ZipInputStream wrapped around the InputStream returned from FTPClient's retrieveFileStream(String remote).

Qwerky
Excellent answer. I think Jack was the first to answer and his answer had some code in it which helped me.
Tommy
Hover your mouse over "answered 1 hour ago" and the tooltip shows you the post time.
Qwerky
+3  A: 

You don't need to create the File object.

If you want to save the file you should pipe the stream directly into a ZipOutputStream

ByteArrayOutputStream out = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(out);

// do whatever with your zip file

If, instead, you want to open the just retrieved file work with the ZipInputStream:

new ZipInputStream(fileClient.retrieveFileStream(String remote));

Just read the doc here and here

Jack
+1  A: 

I think you want:

ZipInputStream zis = new ZipInputStream( new ByteArrayInputStream( out.toByteArray() ) );

Then read your data from the ZipInputStream.

Dave Costa
A: 

As others have pointed out, for what you are trying to do, you don't need to write the downloaded ZIP "file" to the file system at all.

Having said that, I'd like to point out a misconception in your question, that is also reflected in some of the answers.

In Java, a File object does no really represent a file at all. Rather, it represents a file name or *path". While this name or path often corresponds to an actual file, this doesn't need to be the case.

This may sound a bit like hair-splitting, but consider this scenario:

File dir = new File("/tmp/foo");
boolean isDirectory = dir.isDirectory();
if (isDirectory) {
    // spend a long time computing some result
    ...
    // create an output file in 'dir' containing the result
}

Now if instances of the File class represented objects in the file system, then you'd expect the code that creates the output file to succeed (modulo permissions). But in fact, the create could fail because, something deleted the "/tmp/foo", or replaced it with a regular file.

It must be said that some of the methods on the File class do seem to assume that the File object does correspond to a real filesystem entity. Examples are the methods for getting a file's size or timestamps, or for listing the names in a directory. However, in each case, the method is specified to throw an exception if the actual file does not exist or has the wrong type for the operation requested.

Stephen C