Saving BufferedImage using zip compression - java

How would I go about saving a BufferedImage straight to a zip file.
Here is my current code for saving my BufferedImage to a zip file but I do not know how to convert the BufferedImage to a InputStream so that it can be saved to the zip file.
If possible I need to save the BufferedImage straight from RAM without saving it to HDD first
byte[] buffer = new byte[1024];
try
{
FileOutputStream outputStream = new FileOutputStream(PathName + imageData.getFileNumber() + ".zip");
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
ZipEntry imageZipOutput = new ZipEntry(imageData.getFileNumber() + ".png");
zipOutputStream.putNextEntry(imageZipOutput);
//the BufferedImage is stored in imageData.getImage();
//how would I parse the BufferedImage to the InputStream below without saving the png first but straight from RAM
InputStream in = new InputStream();
int len;
while ((len = in.read(buffer)) > 0)
{
zipOutputStream.write(buffer, 0, len);
}
in.close();
zipOutputStream.closeEntry();
zipOutputStream.close();
}

Use ImageIO.write(RenderedImage im,String formatName, OutputStream output) to write the output. Pass a ZipOutputStream for the OutputStream parameter.
Check this page for more info.

Related

Read image and send it via socket - could not open file

I am trying to write a simple server that uses sockets and reads images from disc when it receives http request from browser.
I am able to receive the request, read the image from disc and pass it to the browser (the browser then automatically downloads the image). However, when I try to open the downloaded image, it says:
Could not load image 'img.png'. Fatal error reading PNG image file: Not a PNG file
The same goes for all other types of extensions (jpg, jpeg, gif etc...)
Could you help me out and tell me what am I doing wrong? I suspect that there might be something wrong with the way I read the image or maybe some encoding has to be specified?
Reading the image from disc:
// read image and serve it back to the browser
public byte[] readImage(String path) {
File file = new File(FILE_PATH + path);
try {
BufferedImage image = ImageIO.read(file); // try reading the image first
// get DataBufferBytes from Raster
WritableRaster raster = image.getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return data.getData();
} catch (IOException ex) {
// handle exception...
}
return ("Could not read image").getBytes();
}
Writing the data via socket:
OutputStream output = clientSocket.getOutputStream();
output.write(result);
In this case, the result contains the byte array produced by the readImage method.
EDIT: second try with reading the image as normal file
FileReader reader = new FileReader(file);
char buf[] = new char[8192];
int len;
StringBuilder s = new StringBuilder();
while ((len = reader.read(buf)) >= 0) {
s.append(buf, 0, len);
byte[] byteArray = s.toString().getBytes();
}
return s.toString().getBytes();
You may use ByteArrayOutputStream, like,
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", byteArrayOutputStream);
and then you can write to socket as,
outputStream.write(byteArrayOutputStream.toByteArray());

Zipping files with ZipOutputStream gives inconsistent results

I want to zip a text file using the java.util.ZipOutputStream class. I found two examples on the internet explaining on how to do that. This led me to the two possible implementations shown below. While both methods produce 'healthy zip files', my problem is that on every run the binary content of the file is slightly different (around the 10th byte). Does someone know if
This is intended behaviour
There is a way to always produce exactly the same result
Here is my current code:
public byte[] getZipByteArray(String fileName) throws IOException
{
byte[] result = new byte[0];
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry ze = new ZipEntry(fileName);
zos.putNextEntry(ze);
InputStream inputStream = ZipCompression.class.getResourceAsStream(fileName);
int len;
while ((len = inputStream.read(buffer)) > 0)
{
zos.write(buffer, 0, len);
}
zos.closeEntry();
zos.close();
result = baos.toByteArray();
return result;
}
public byte[] ZipByteArrayBuffered(String fileName) throws IOException
{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
ZipOutputStream zipOutputStream = new ZipOutputStream(bufferedOutputStream);
File file = new File(fileName);
InputStream fileInputStream = ZipCompression.class.getResourceAsStream(file.getName());
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
IOUtils.copy(fileInputStream, zipOutputStream);
fileInputStream.close();
zipOutputStream.closeEntry();
if (zipOutputStream != null)
{
zipOutputStream.finish();
zipOutputStream.flush();
IOUtils.closeQuietly(zipOutputStream);
}
IOUtils.closeQuietly(bufferedOutputStream);
IOUtils.closeQuietly(byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
Byte 10 starts the file modification date and so this will always differ. See Wikipedia for the details of the zip file format.

Creating default file for my application with images and text

I have the following problem:
I need to save information that is currently on my application, and this information consists on images (.gif and .jpg) and text. I want to save everything in one single file, because saving only the image path for these images may cause an error if the user deletes any of the images. How can I save image and text into one single file using Java?
You can zip the files under one file
Code Example:
byte[] buffer = new byte[1024];
try{
FileOutputStream fos = new FileOutputStream("C:\\MyFile.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze= new ZipEntry("spy.log");
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream("C:\\spy.log");
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
zos.closeEntry();
//remember close it
zos.close();
System.out.println("Done");
}catch(IOException ex){
ex.printStackTrace();
}

Writing inputstream to file - no file found

I'm trying to write inputstream to a file, but it never gets written on disk, I just get the error file doesnt exist. The file I open is a drawable icluded in the project, I would like to save it to sd card. This is what I have so far:
File storagePath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/tester");
InputStream inputStream = getResources().openRawResource(R.drawable.test);
OutputStream out = new FileOutputStream(new File(storagePath, "test.png"));
byte buffer[] = new byte[900];
int len;
while ((len = inputStream.read(buf)) > 0)
out.write(buffer, 0, len);
out.close();
inputStream.close();
Your tester directory doesn't exist. Check for it and create it if necessary before opening your FileOutputStream.

To copy zip file into another zipfile

Currently I am using below code to copy zip inside another zip.But when zip file size increases eg:2GB, program is throwing out of memory error.I have increased xmx to 1024, still prfoblem is same.Is thr s any alternate method to handle large files ?
public static void zipFile(File srcFile, File zipFile)
throws FileNotFoundException, IOException {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(zipFile);
ZipOutputStream out = new ZipOutputStream(
new BufferedOutputStream(dest));
// out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[BUFFER];
FileInputStream fi = new FileInputStream(srcFile);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(srcFile.getName());
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
out.close();
}
You are only copying bytes when you come right down to it. You don't need to process either file as a Zip file. Just copy the bytes.
Can you try FileChannel.transferTo method? It's more efficient. Since this is done at OS level, I'm assuming it shouldn't depend on Java Heap size.
If that fails too take a look at this question.

Categories

Resources