Unzipping an image failing using buffer from gzip format - java

I am zipping the files using , but while unzipping them, I am facing two problems,
when unzipped without buffer its getting back to original form, but when I use buffer its not able to do it correctly.
the size of the unzipped file is more than the original file.
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
try (FileInputStream fis = new FileInputStream(zipFilePath);
GZIPInputStream inflaterInputStream = new GZIPInputStream(fis)) {
int data;
**while ((data = inflaterInputStream.read()) != -1) {//without buffer**
fos.write(data);
}
}
}
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
byte[] buffer = new byte[12048];
try (FileInputStream fis = new FileInputStream(zipFilePath);
GZIPInputStream inflaterInputStream = new GZIPInputStream(fis)) {
int data;
**while ((data = inflaterInputStream.read(buffer)) != -1) {//with buffer**
fos.write(data);
}
}
}

You're not writing the buffer, but data which is the length of bytes read...
Corrected:
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
byte[] buffer = new byte[12048];
try (InputStream fis = new FileInputStream(zipFilePath);
InputStream inflaterInputStream = new GZIPInputStream(fis)) {
int data;
while ((data = inflaterInputStream.read(buffer)) != -1) {//with buffer**
fos.write(buffer, 0, data);
}
}
}
You'd be better off using apache.commons-io
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
try (InputStream fis = new FileInputStream(zipFilePath);
InputStream inflaterInputStream = new GZIPInputStream(fis)) {
IOUtils.copy(fis, fos);
}
}

Related

Transfer a huge file using StreamingOutput without incurring the wrath of heapSpace

I have been trying to stream|transfer a huge file available in the local file-system over restapi using streamingoutput. I keep running into heapSpace error. Can anyone help me figure out what I am doing wrong? As per my understanding, streamingoutput shouldn't keep the file in memory.
Please find the code below:
public Response getBulkBillDownload(#QueryParam("requestID") String requestID,
#QueryParam("zipFileName") String zipFileName) throws RestException {
StreamingOutput stream = null;
try {
File file = null;
Optional<File> document = getCorporatePaymentManager().getBulkBillDownloadResponse(requestID, zipFileName);
if (document.isPresent()) {
file = document.get();
} else {
throw new RestException("File not found");
}
final FileInputStream fStream = new FileInputStream(file);
// register stream to Response and it will callback with server OutputStream
stream = new StreamingOutput() {
#Override
public void write(OutputStream output) throws IOException, WebApplicationException {
pipe(fStream, output);
}
};
} catch (Exception e) {
handleException(e);
}
return Response.status(200).entity(stream).header("Content-Disposition", "attachment; filename=" + zipFileName)
.build();
}
private void pipe(InputStream is, OutputStream os) throws IOException {
byte[] buf=new byte[1024];
int bytesread = 0, bytesBuffered = 0;
while( (bytesread = is.read( buf )) > -1 ) {
os.write( buf, 0, bytesread );
bytesBuffered += bytesread;
if (bytesBuffered > 1024 * 1024) { //flush after 1MB
bytesBuffered = 0;
os.flush();
}
}
os.close();
}

Download/Display file stored in SQL table

I've taken over a project where the file upload functionality is broken. Currently when a file is uploaded it is converted to a byteArray like so and then stored in a SQL table
public static byte[] saveAttachment(String filePath) throws IOException{
InputStream inputStream = new FileInputStream(filePath);
byte[] buffer = new byte[1048576];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while((bytesRead = inputStream.read(buffer)) != -1){
output.write(buffer, 0 , bytesRead);
}
inputStream.close();
return output.toByteArray();
}
I can't say I agree with the approach that has been taken but alas I must work with it. My question becomes how do I go about retrieving this file to display?
I have read
https://wiki.apache.org/tapestry/Tapestry5HowToStreamAnExistingBinaryFile
And tried (which didn't work)
#OnEvent(component="viewAttachment")
private Object viewAttachment(){
final File getFile();
final OutputStreamResponse response = new OutputStreamResponse() {
public String getContentType() {
return "image/jpg";
}
public void prepareResponse(Response response) {
response.setHeader ("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
}
#Override
public void writeToStream(OutputStream out) throws IOException {
try {
InputStream in = new FileInputStream(file);
IOUtils.copy(in,out);
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
return response;
}
However I am not sure this is the proper/optimal solution.
Assuming that row.getBytes() returns your image as byte array, and row.getName() is image name:
return new StreamResponse() {
#Override
public String getContentType() {
return "image/jpeg";
}
#Override
public InputStream getStream() throws IOException {
return new ByteArrayInputStream(row.getBytes());
}
#Override
public void prepareResponse(Response response) {
response.setHeader("Content-Disposition", "attachment; filename=\"" + row.getName() + "\"");
}
};
Its better to save the file in a location and save the location in the database. This will help to have size of database.
Also file is available and can retrieve easily without heavy database object.
Or you can add the BLOB column in database and store the file in database.
Convert file into File object
File image = new File("D:\\a.gif");
FileInputStream fis = new FileInputStream(image);
stmt.setBinaryStream(1, fis, (int) image.length());
Add retrieve it using
File image = new File("D:\\java.gif");
FileOutputStream fos = new FileOutputStream(image);
byte[] buffer = new byte[1];
InputStream is = resultSet.getBinaryStream(3);
while (is.read(buffer) > 0) {
fos.write(buffer);
}
fos.close();

Compressing byte arrays using GZIP in java

I've been working on a function that compresses an array of bytes using GZIP and sends it through an outputStream that belongs to a socket. It downloads fine but when trying to decompress on my PC it says that file is corrupted.
private void Zip(byte[] datatocompress)
{
ZipOutputStream zippoutstream = new ZipOutputStream(outputstream);
zippoutstream.putNextEntry(new ZipEntry("file.html"));
zippoutstream.write(datatocompress);
zippoutstream.closeEntry();
zippoutstream.flush();
zippoutstream.close();
}
No idea about what crashes. Any suggestion?
public static byte[] gzip(byte[] val) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(val.length);
GZIPOutputStream gos = null;
try {
gos = new GZIPOutputStream(bos);
gos.write(val, 0, val.length);
gos.finish();
gos.flush();
bos.flush();
val = bos.toByteArray();
} finally {
if (gos != null)
gos.close();
if (bos != null)
bos.close();
}
return val;
}
/**
* Compress
*
* #param source
*
* #param target
*
* #throws IOException
*/
public static void zipFile(String source, String target) throws IOException {
FileInputStream fin = null;
FileOutputStream fout = null;
GZIPOutputStream gzout = null;
try {
fin = new FileInputStream(source);
fout = new FileOutputStream(target);
gzout = new GZIPOutputStream(fout);
byte[] buf = new byte[1024];
int num;
while ((num = fin.read(buf)) != -1) {
gzout.write(buf, 0, num);
}
} finally {
if (gzout != null)
gzout.close();
if (fout != null)
fout.close();
if (fin != null)
fin.close();
}
}

DeflaterOutputStream won't output valid file

I'm using DeflaterOutputStream in combination with Buffered input and output streams, trying to just compress a simple file which I should be able to decompress with the second program (it also adds a number at the end of a line but this is irrelevant). However, it's not creating a valid compressed file. When I try to decompress it, it just creates a blank file. I think it might have something to do with flushing. Any thoughts?
public class Program {
static String inputFileName = "inputfile.txt";
static String outputFileName = "outputfile.txt";
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream(inputFileName);
BufferedInputStream inputBuff = new BufferedInputStream(fileInputStream);
FileOutputStream fileOutputStream = new FileOutputStream(outputFileName);
BufferedOutputStream outputBuff = new BufferedOutputStream(fileOutputStream);
DeflaterOutputStream deflater = new DeflaterOutputStream(outputBuff);
int fileByte;
while ((fileByte =inputBuff.read()) != -1)
{
deflater.write(fileByte);
}
deflater.flush();
outputBuff.flush();
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Program2 {
static String inputFileName = "outputfile.txt";
static String outputFileName = "decoutputfile.txt";
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream(inputFileName);
BufferedInputStream inputBuff = new BufferedInputStream(fileInputStream);
FileOutputStream fileOutputStream = new FileOutputStream(outputFileName);
BufferedOutputStream outputBuff = new BufferedOutputStream(fileOutputStream);
InflaterOutputStream inflater = new InflaterOutputStream(outputBuff);
int fileByte;
int lineCount = 1;
while ((fileByte =inputBuff.read()) != -1)
{
if (fileByte == '\n'){
inflater.write(lineCount);
lineCount++;
}
inflater.write(fileByte);
}
inflater.flush();
outputBuff.flush();
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Write mp3 file to disk while playing in Java

I have an application playing remote MP3 files over HTTP using the JLayer/BasicPlayer libraries. I want to save the played mp3 files to disk without re-downloading them.
This is the code using the JLayer based BasicPlayer for Playing the MP3 file.
String mp3Url = "http://ia600402.us.archive.org/6/items/Stockfinster.-DeadLinesutemos025/01_Push_Push.mp3";
URL url = new URL(mp3Url);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
BasicPlayer player = new BasicPlayer();
player.open(bis);
player.play();
How would I save the mp3 file to disk?
To avoid having to go through the bytes twice, you need to wrap the input stream from the connection in a filter that writes any data that is read to an output stream, i.e. a kind of a "tee pipe input stream." Such a class is not that difficult to write yourself, but you can save the work by using TeeInputStream from the Apache Commons IO library.
Apache Commons IO: http://commons.apache.org/io/
TeeInputStream javadoc: http://commons.apache.org/io/apidocs/org/apache/commons/io/input/TeeInputStream.html
Edit: Proof-of-concept:
import java.io.*;
public class TeeInputStream extends InputStream {
private InputStream in;
private OutputStream out;
public TeeInputStream(InputStream in, OutputStream branch) {
this.in=in;
this.out=branch;
}
public int read() throws IOException {
int read = in.read();
if (read != -1) out.write(read);
return read;
}
public void close() throws IOException {
in.close();
out.close();
}
}
How to use it:
...
BufferedInputStream bis = new BufferedInputStream(is);
TeeInputStream tis = new TeeInputStream(bis,new FileOutputStream("test.mp3"));
BasicPlayer player = new BasicPlayer();
player.open(tis);
player.play();
BufferedInputStream in = new BufferedInputStream(is);
OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(savePathAndFilename)));
byte[] buf = new byte[256];
int n = 0;
while ((n=in.read(buf))>=0) {
out.write(buf, 0, n);
}
out.flush();
out.close();
You can first write the stream to disk with FileInputStream. Then reload the stream from file.
Wrap you own InputStream
class myInputStream extends InputStream {
private InputStream is;
private FileOutputStream resFile;
public myInputStream(InputStream is) throws FileNotFoundException {
this.is = is;
resFile = new FileOutputStream("path_to_result_file");
}
#Override
public int read() throws IOException {
int b = is.read();
if (b != -1)
resFile.write(b);
return b;
}
#Override
public void close() {
try {
resFile.close();
} catch (IOException ex) {
}
try {
is.close();
} catch (IOException ex) {
}
}
}
and use
InputStream is = conn.getInputStream();
myInputStream myIs = new myInputStream(is);
BufferedInputStream bis = new BufferedInputStream(myIs);

Categories

Resources