How to create a ZipFile from a byte array in Java - java

In Java you have to do
new ZipFile(new File("xxx.zip"));
to unzip a zip file.
Now I get a byte array whose content is a zip file. I get this byte array from database instead of a file. I would like to unzip this "byte array file" but there is no ZipFile constructor for byte array or String (I mean the content instead of the file path).
Is there any solution? (Of course I do not want to write this byte array to an actual file and read it into memory again.)
Thanks!

Use a ByteArrayInputStream inside the ZipInputStream which is created from a byte array
byte[] ba;
InputStream is = new ByteArrayInputStream(ba);
InputStream zis = new ZipInputStream(is);
Use zis to read the contents uncompressed

Implementations of ZipFile requires it to be a file. Memory mapping may be used, for instance. In general it is assumed that the archive may be huge.
As #Perception mentions, ZipInputStream can be used to read sequentially through the stream. Third-party libraries may be available to replace ZipFile.

Related

Convert GZIPOutputStream to byte array

I already have a GZIPOutput stream which has already defined. Now I want to convert it to a byte array.
I tried the code below. But it gives an error.
GZIPOutputStream zipStream = createGZIP();
byte[] compressedData = zipStream.toByteArray();
error : cannot resolve method "toByteArray()"
checked GZIP compression to a byte array , but it is inputting a byte[]. I need to convert a gzip which I already have.
I have a GZIPOutput stream which has already defined. Now I want to convert it to a byte array.
You will need to modify the method that is creating the GZIPOutputStream so that it sends it to a ByteArrayOutputStream.
Alternatively, after closing the FileOutputStream for the file where you are (presumably) writing the compressed data, open it for input and read it into a byte array.
Concerning your current attempt:
GZIPOutputStream zipStream = createGZIP();
byte[] compressedData = zipStream.toByteArray();
This approach is not going to work.
GZIPOutputStream provides no API methods for retrieving the compressed data.
GZIPOutputStream provides no API methods for retrieving the stream that GZIPOutputStream is writing to. (And even if there was, most OutputStream types don't allow you to retrieve the data ...)
In general, it is better to find and read the javadocs for the classes that you use. Programming by guessing what methods they provide is liable to lead you to waste your time when your guess are wrong.

Java ByteBuffer for Zipfile

I have a binary file that contains big endian data. I am using this code to read it in
FileChannel fileInputChannel = new FileInputStream(fileInput).getChannel();
ByteBuffer bb = ByteBuffer.allocateDirect((int)fileInputChannel.size());
while (bb.remaining() > 0)
fileInputChannel.read(bb);
fileInputChannel.close();
bb.flip();
I have to do something identical for zip files. In other words decompress the file from a zip file and order it. I understand I can read it in via ZipInputStream but then I have to provide the coding for the "endianness". With ByteBuffer you can use ByteOrder.
Is there an NIO alternative for zip files ?
If you have your ZipInputStream, just use Channels.newChannel to convert it to a Channel then proceed as you wish. But you should keep in mind that it might be possible that a ZipInputStream can’t predict its uncompressed size so you might have to guess the appropriate buffer size and possibly re-allocate a bigger buffer when needed. And, since the underlying API uses byte arrays, there is no benefit in using direct ByteBuffers in the case of ZipInputStream, i.e. I recommend using ByteBuffer.allocate instead of ByteBuffer.allocateDirect for this use case.
By the way you can replace while(bb.remaining() > 0) with while(bb.hasRemaining()). And since Java 7 you can use FileChannel.open to open a FileChannel without the detour via FileInputStream.

Java open stream from an arbitrary location in file

I want to get a Stream from some arbitrary position in an existing file, for example I need to read/write from/to a file starting with 101th byte.
Is it safe to use something like that?
final FileInputStream fin = new FileInputStream(f);
fin.skip(100);
Skip javadoc tells that it may sometimes skip lesser number of bytes than specified.
What should I do then?
you can't write using a FileInputStream. you need to use a RandomAccessFile if you want to write to arbitrary locations in a file. eunfortunately, there is no easy way to use a RandomAccessFile as an InputStream/OutputStream (looks like #aix may have a good suggestion for adapting RandomAccessFile to InputStream/OutputStream), but there are various example adapters available online.
another alternative is to use a FileChannel. you can set the position of the FileChannel directly, then use the Channels utility methods to get InputStream/OutputStream adapters on top of the Channel.
How about the following:
final RandomAccessFile raf = new RandomAccessFile(f, mode);
raf.seek(100);
final FileInputStream fin = new FileInputStream(raf.getFD());
// read from fin

How to overwrite some bytes in a file?

I've created a file using java.io.File, FileInputStream & FileOutputStream. Suppose that I want to change the value of some bytes in the file (for instance from the byte 15 to 35) without changing the size of the file. I've tried creating a RandomAccessFile object and then use RandomAccessFile.seek to move to byte number 15, writing my new bytes and then closing the file. The file has changed its size. What's wrong with this approach, and how can this be done successfully?
Are you sure you are writing a byte to the RandomAccessFile? If you are calling the method:
file.write(35);
Then it is actually writing 35 as an int which is 4 bytes. If you want to write a single byte try:
file.writeByte(35);

Creating a File from byte array

So - I've got a third party library that needs a File as input. I've got a byte array.
I don't want to write the bytes to disk .. I'd like to keep this in memory. Any idea on how I can create a File from the provided byte array (without writing to disk)?
Sorry, not possible. A File is inherently an on-disk entity, unless you have a RAM disk - but that's not something you can create in Java.
That's exactly the reason why APIs should not be based on File objects (or be overloaded to accept an InputStream).
There's one possibility, but it's a real long-shot.
If the API uses new FileReader(file) or new FileInputStream(file) then you're hosed, but...
If it converts the file to a URL or URI (using toURL() or toURI()) then, since File is not final, you can pass in a subclass of File in which you control the construction of the URL/URI and, more importantly, the handler.
But the chances are VERY slim!
So I see there is an accepted answer (and this is old), but I found a way to do this. I was using the IDOL On Demand API and needed to convert a byte array to a File.
Here is an example of taking a byte array of an image and turning into a File:
//imageByte is the byte array that is already defined
BufferedImage image = null;
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
// write the image to a file
File outputfile = new File("image.png");
ImageIO.write(image, "png", outputfile);
And so outputfile is a File that can be used later in your program.

Categories

Resources