ByteArrayOutputStream with zipStream to InputStream - java

Currently I want to create a zip file and make it available in the browser via HTTP response. Because I don't want to cache files on the hard disk I have to use streams all the time. The problem is that after creating the zip file I only have one ByteArrayOutputStream, but for sending the response I need an InputStream.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(baos);
// filling zip with multiple ZipEntrys
IOUtils.closeQuietly(zip);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
IOUtils.closeQuietly(baos);
The line
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
gives me a null pointer every time.
What is wrong? Is there a stream not completely written? Additionally I have to do everything with Java 6 and Apache commons.

Related

How can I transform an uncompressed file into zipped bytes?

In Java for a JUnit test, I am trying to mock a function that downloads a Zip File from another external API's endpoint. To simulate the download, I need to zip a test file and transform it into bytes to use as the mock's return value. I do not need to write the zipped file back to the file system but use the bytes raw as they are.
mock(zipReturner.getZipBytes()).thenReturn(testFileAsZippedBytes("testFile.txt"))
private Optional<byte[]> testFileAsZippedBytes(String testFile) {
???
}
Sharing my answer, because all the other examples I found are much heavier, require many more lines of code looping over bytes, or require using external libraries to do the same thing.
To do this without the above, use a combination of ByteArrayOutputStream, as it has the toByteArray function, ZipOutputStream to write zipped bytes to the ByteArrayOutputStream and FileInputStream to read the test file from the file system.
private Optional<byte[]> testFileAsZippedBytes(String filePath, String fileName) throws IOException {
try (
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
FileInputStream fileInputStream = new FileInputStream(filePath + fileName);
) {
ZipEntry zipEntry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(zipEntry);
zipOutputStream.write(fileInputStream.readAllBytes());
zipOutputStream.finish();
return Optional.of(byteArrayOutputStream.toByteArray());
}
}
Use ZipEntry to add the file as an entry to the ZipOutputStream and write the bytes to the zip. Use zipOutputStream.finish() to ensure all contents are written to the stream and are ready to be consumed in the ByteArrayOutputStream, otherwise it was my experience that you would only get partial data when you call byteArrayOutputStream.toByteArray().

Creating ZIP file in memory

I need to create a ZIP file which consists of files that are created on-the-fly and have no persistence on the file system.
For example: I want to create an SQLite database in memory and after populating it with data I want to add it to a - not yet existing - ZIP file and than I want to actually write this ZIP file to the file system.
I found several approaches where the files, which are going to be the content of the archive, have to be read from the file system.
Is there actually a way to archive what I want to do? I hoped that compress-commons would help me but apparently they don't.
Do I miss something?
If the in memory object you are trying to zip is serializable, then this is quite easy.
You can take any serializable instance and turn it in to a byte[]. I have a utility method to do this:
public static byte[] convertToBytes(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(object);
out.flush();
return bos.toByteArray();
}
}
Once you have a that object represented in bytes, you can use a ZipOutputStream to zip it up:
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream out = new GZIPOutputStream(bos); ) {
out.write(bytes);
out.finish();
byte[] compressed = bos.toByteArray(); // this is my compressed data
}
(I use Gzip here for simplicity but you can also create a zip with multiple entries, for example).

Zipping a file and sending it without saving the zipped file in the process

I want to open a specific file and zip it and send the byte array of the zipped result over UDP.
Now I checked the java zip API but it only give me to save the zipped file to the computer and opening it again and send it would be inefficiency.
Is there any way to do what I need without writing an implementation of the compression algorithm of my own ?
You cand wrap your ZipOutputStream around a ByteArrayOutputStream and get the bytes out of the ByteArrayOutputStream.
Something like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
//write the entries
zos.close();
byte[] bytes = baos.toByteArray();

Sending file through ObjectOutputStream and then saving it in Java?

I have this simple Server/Client application. I'm trying to get the Server to send a file through an OutputStream (FileOutputStream, OutputStream, ObjectOutputStream, etc) and receive it at the client side before saving it into an actual file. The problem is, I've tried doing this but it keeps failing. Whenever I create the file and write the object I received from the server into it, I get a broken image (I just save it as a jpg, but that shouldn't matter). Here are the parts of the code which are most likely to be malfunctioning (all the seemingly un-declared objects you see here have already been declared beforehand):
Server:
ObjectOutputStream outToClient = new ObjectOutputStream(
connSocket.getOutputStream());
File imgFile = new File(dir + children[0]);
outToClient.writeObject(imgFile);
outToClient.flush();
Client:
ObjectInputStream inFromServer = new ObjectInputStream(
clientSocket.getInputStream());
ObjectOutputStream saveImage = new ObjectOutputStream(
new FileOutputStream("D:/ServerMapCopy/gday.jpg"));
saveImage.writeObject(inFromServer.readObject());
So, my problem would be that I can't get the object through the stream correctly without getting a broken file.
A File object represents the path to that file, not its actual content. What you should do is read the bytes from that file and send those over your ObjectOutputStream.
File f = ...
ObjectOutputStream oos = ...
byte[] content = Files.readAllBytes(f.toPath);
oos.writeObject(content);
File f=...
ObjectInputStream ois = ...
byte[] content = (byte[]) ois.readObject();
Files.write(f.toPath(), content);
You are not actually transferring the file, but the File instance from Java. Think of your File object as a (server-)local handle to the file, but not its contents. For transferring the image, you'd actually have to read it on the server first.
However, if you're just going to save the bytes on the client anyway, you can forget about the ObjectOutputStream to begin with. You can just transfer the bytes stored in the File. Take a look at the FileChannel class and its transferTo and transferFrom methods as a start.

Java converting an image to an input stream WITHOUT creating a file

For an applet I'm working on I need to convert a BufferedImage file to an input stream so that I can upload the image to my MySQL server. Originally I was using this code:
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection =
DriverManager.getConnection(connectionURL, "user", "pass");
psmnt = connection.prepareStatement(
"insert into save_image(user, image) values(?,?)");
psmnt.setString(1, username);
ImageIO.write(image, "png", new File("C://image.png"));
File imageFile = new File("C://image.png");
FileInputStream fis = new FileInputStream(imageFile);
psmnt.setBinaryStream(2, (InputStream)fis, (fis.length()));
int s = psmnt.executeUpdate();
if(s > 0) {
System.out.println("done");
}
(while catching the relevant exceptions) The code hangs on the part where the applet attempts to save the image to the computer. The code worked perfectly in Eclipse or whenever I ran the applet from the localhost, so I'm assuming the problem is in the privileges that the applet has in saving files to the user's computer.
I was just was wondering if there was a way to turn the image file into an inputstream without having to save a file to the user's computer. I tried using:
ImageIO.createImageInputStream(image);
But then I couldn't convert the ImageInputStream back to an InputStream. Any Suggestions?
Thanks!
Typically you would use a ByteArrayOutputStream for that purpose. It acts as an in-memory stream.
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image,"png", os);
InputStream fis = new ByteArrayInputStream(os.toByteArray());
Have you tried writing to a ByteArrayOutputStream and then creating a ByteArrayInputStream from that data to read from? (Call toArray on the ByteArrayOutputStream and then call the constructor of ByteArrayInputStream which will wrap that byte array.)
Be careful using BytArray streams: if the image is large, that code will fail. i have not done much applet coding, but it's possible that the temp dir is available for writing (e.g. File.createTempFile() ).

Categories

Resources