does someone have an idea why this code to create a gzipped string is not working? CLI gzip on a Mac can't open the resulting file: "Not in gz format".
Please note: I need the string, not the file. Creating the gzipped file directly works, so does writing the JSON without zipping it.
The file writing in this example is just for testing purposes.
public someMethod {
String gzippedString = this.gzippedString(finalJSONObject.toJSONString());
OutputStream outputStream = new FileOutputStream(new File(this.jsonOutputPath + "/myfile.gz"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.append(gzippedString);
writer.close();
}
private String gzippedString(String inputString) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(inputString.getBytes());
gzipOutputStream.close();
outputStream.close();
String gzippedString = outputStream.toString();
return gzippedString;
}
EDIT:
chrylis showed me the way:
public void someMethod() {
byte[] byteArray = this.gzippedByteArray(finalJSONObject.toJSONString());
FileOutputStream out = new FileOutputStream(this.jsonOutputPath + "/myfile.gz");
out.write(byteArray);
out.close();
}
private byte[] gzippedByteArray(String inputString) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(inputString.getBytes());
gzipOutputStream.close();
outputStream.close();
byte[] gzippedByteArray = outputStream.toByteArray();
return gzippedByteArray;
}
This results in a working gzipped JSON.
Thanks a lot!
You're round-tripping binary data through a String, which has a character encoding and other such mangling. Use the byte[] directly instead.
Related
So my problem sounds like this. I need to make a base64 encoded string of a file and for this, I use this method:
public String getStringFile(File f) {
InputStream inputStream = null;
String encodedFile= "", lastVal;
try {
inputStream = new FileInputStream(f.getAbsolutePath());
byte[] buffer = new byte[10240];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
output64.close();
encodedFile = output.toString();
} catch (Exception e) {
e.printStackTrace();
}
lastVal = encodedFile;
return lastVal;
}
and the thing is when I try to encode file something around 20 Mb (exact file size is 19,35 Mb) I get an OutOfMemoryException.
Before:
After:
What am I doing wrong and how can I fix this issue? Thanks in advance.
What am I doing wrong
You are attempting to encode a ~20MB file using base64 into a string. You will not have adequate heap space on many Android devices to have a single memory allocation that large.
how can I fix this issue?
If "this issue" is "create a ~26MB string of base64-encoded data", there is no reliable way to do this. You would have to find some other solution to whatever problem you are trying to solve by creating such a string.
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
If you upload the base64 yourself with HttpUrlConnection you can do way with the ByteArrayOutputStream and replace above lines -while directly uploading- with
OutputStream output = con.getOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
Untested.
You could also directly base64 encode to a FileOutputStream of course.
OutputStream output = new FileOutputStream(......);
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
and then upload that file with POJO.
I'm trying load an image in a string and after do something with this String, save the image.
The problem appear when i try to asignate the value of the FileInputStream to the String targetFileStr. If i don't to this, and I save the image, everything it's ok, but when i save it on the String, the image change, no matter if I try save the image from the String or from the FileInputStream.
FileInputStream fis = null;
File file = new File("image.png");
fis = new FileInputStream(file);
String targetFileStr = IOUtils.toString(fis, "UTF-8");
*InputStream inputStream = IOUtils.toInputStream(targetFileStr, "UTF-8");
*InputStream inputStream = fis;
// no matter which one i use, both ways fail
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(new File("image2.png"));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (Exception e) {
e.printStackTrace();
}
You may want to consider converting the image into a String via Base64 encoding/decoding. This is an example of encoding.
After encoding, you can modify the String (actually you create new strings, you cannot modify the existing one), but be sure to produce valide base64-encoded outputs, otherwise you won't be able to decode.
I have the following problem: I have an HttpServlet that create a file and return it to the user that have to receive it as a download
byte[] byteArray = allegato.getFile();
InputStream is = new ByteArrayInputStream(byteArray);
Base64InputStream base64InputStream = new Base64InputStream(is);
int chunk = 1024;
byte[] buffer = new byte[chunk];
int bytesRead = -1;
OutputStream out = new ByteArrayOutputStream();
while ((bytesRead = base64InputStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
As you can see I have a byteArray object that is an array of bytes (byte[] byteArray) and I convert it into a file in this way:
First I convert it into an InputStream object.
Then I convert the InputStream object into a Base64InputStream.
Finally I write this Base64InputStream on a ByteArrayOutputStream object (the OutputStream out object).
I think that up to here it should be ok (is it ok or am I missing something in the file creation?)
Now my servlet have to return this file as a dowload (so the user have to receive the download into the browser).
So what have I to do to obtain this behavior? I think that I have to put this OutputStream object into the Servlet response, something like:
ServletOutputStream stream = res.getOutputStream();
But I have no idea about how exactly do it? Have I also to set a specific MIME type for the file?
It's pretty easy to do.
byte[] byteArray = //your byte array
response.setContentType("YOUR CONTENT TYPE HERE");
response.setHeader("Content-Disposition", "filename=\"THE FILE NAME\"");
response.setContentLength(byteArray.length);
OutputStream os = response.getOutputStream();
try {
os.write(byteArray , 0, byteArray.length);
} catch (Exception excp) {
//handle error
} finally {
os.close();
}
EDIT:
I've noticed that you are first decoding your data from base64, the you should do the following:
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[chunk];
int bytesRead = -1;
while ((bytesRead = base64InputStream.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
You do not need the intermediate ByteArrayOutputStream
With org.apache.commons.compress.utils.IOUtils you can just "copy" from one file or stream (e.g. your base64InputStream) to the output stream:
response.setContentType([your file mime type]);
IOUtils.copy(base64InputStream, response.getOutputStream());
response.setStatus(HttpServletResponse.SC_OK);
You'll find that class here https://mvnrepository.com/artifact/org.apache.commons/commons-compress
A similar class (also named IOUtils) is also in Apache Commons IO (https://mvnrepository.com/artifact/commons-io/commons-io).
I am currently trying to read in data from a server response. I am using a Socket to connect to a server, creating a http GET request, then am using a Buffered Reader to read in data. Here is what the code looks like compacted:
Socket conn = new Socket(server, 80);
//Request made here
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String response;
while((response = inFromServer.readLine()) != null){
System.out.println(response);
}
I would like to read in the data, instead of as a String, as a byte array, and write it to a file. How is this possible? Any help is greatly appreciated, thank you.
You need to use a ByteArrayOutputStream, do something like the below code:
Socket conn = new Socket(server, 80);
//Request made here
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int readBytes = -1;
while((readBytes = is.read(buffer)) > 1){
baos.write(buffer,0,readBytes);
}
byte[] responseArray = baos.toByteArray();
One way is to use Apache commons-io IOUtils
byte[] bytes = IOUtils.toByteArray(inputstream);
With plain java:
ByteArrayOutputStream output = new ByteArrayOutputStream();
try(InputStream stream = new FileInputStream("myFile")) {
byte[] buffer = new byte[2048];
int numRead;
while((numRead = stream.read(buffer)) != -1) {
output.write(buffer, 0, numRead);
}
} catch(IOException e) {
e.printStackTrace();
}
// and here your bytes
byte[] myDesiredBytes = output.toByteArray();
If you are not using Apache commons-io library in your project,I have pretty simple method to do the same without using it..
/*
* Read bytes from inputStream and writes to OutputStream,
* later converts OutputStream to byte array in Java.
*/
public static byte[] toByteArrayUsingJava(InputStream is)
throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int reads = is.read();
while(reads != -1){
baos.write(reads);
reads = is.read();
}
return baos.toByteArray();
}
My application is receiving email through SMTP server. There are one or more attachments in the email and email attachment return as byte[] (using sun javamail api).
I am trying to zip the attachment files on the fly without writing them to disk first.
What is/are possible way to achieve this outcome?
You can use Java's java.util.zip.ZipOutputStream to create a zip file in memory. For example:
public static byte[] zipBytes(String filename, byte[] input) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry entry = new ZipEntry(filename);
entry.setSize(input.length);
zos.putNextEntry(entry);
zos.write(input);
zos.closeEntry();
zos.close();
return baos.toByteArray();
}
I have the same problem but i needed a many files in a zip.
protected byte[] listBytesToZip(Map<String, byte[]> mapReporte) throws IOException {
String extension = ".pdf";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
for (Entry<String, byte[]> reporte : mapReporte.entrySet()) {
ZipEntry entry = new ZipEntry(reporte.getKey() + extension);
entry.setSize(reporte.getValue().length);
zos.putNextEntry(entry);
zos.write(reporte.getValue());
}
zos.closeEntry();
zos.close();
return baos.toByteArray();
}
You can create a zip file from byte array and return to ui streamedContent
public StreamedContent getXMLFile() {
try {
byte[] blobFromDB= null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
String fileName= "fileName";
ZipEntry entry = new ZipEntry(fileName+".xml");
entry.setSize(byteArray.length);
zos.putNextEntry(entry);
zos.write(byteArray);
zos.closeEntry();
zos.close();
InputStream is = new ByteArrayInputStream(baos.toByteArray());
StreamedContent zipedFile= new DefaultStreamedContent(is, "application/zip", fileName+".zip", Charsets.UTF_8.name());
return fileDownload;
} catch (IOException e) {
LOG.error("IOException e:{} ",e.getMessage());
} catch (Exception ex) {
LOG.error("Exception ex:{} ",ex.getMessage());
}
}
byte[] createReport() {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipArchiveOutputStream zipOutputStream = new
ZipArchiveOutputStream(byteArrayOutputStream);
zipOutputStream.setMethod(ZipArchiveOutputStream.STORED);
zipOutputStream.setEncoding(ENCODING);
String text= "text";
byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
ArchiveEntry zipEntryReportObject = newStoredEntry("file.txt", textBytes);
zipOutputStream.putArchiveEntry(zipEntryReportObject);
zipOutputStream.write(textBytes);
zipOutputStream.closeArchiveEntry();
zipOutputStream.close();
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
return null;
}
and
ArchiveEntry newStoredEntry(String name, byte[] data) {
ZipArchiveEntry zipEntry = new ZipArchiveEntry(name);
zipEntry.setSize(data.length);
zipEntry.setCompressedSize(zipEntry.getSize());
CRC32 crc32 = new CRC32();
crc32.update(data);
zipEntry.setCrc(crc32.getValue());
return zipEntry;
}
Maybe the java.util.zip package might help you
Since you're asking about how to convert from byte array I think (not tested) you can use the ByteArrayInputStream method
int read(byte[] b, int off, int len)
Reads up to len bytes of data into an array of bytes from this input stream.
that you will feed to
ZipInputStream This class implements an input stream filter for reading files in the ZIP file format.
You have to use a ZipOutputStream for that.
http://java.sun.com/javase/6/docs/api/java/util/zip/ZipOutputStream.html
ByteArrayInputStream bais = new ByteArrayInputStream(retByte);
ZipInputStream zis = new ZipInputStream(bais);
zis.getNextEntry();
Scanner sc = new Scanner(zis);
while (sc.hasNextLine()) {
System.out.println("-->:" +sc.nextLine());
}
zis.closeEntry();
zis.close();
public static void createZip(byte[] data) throws ZipException {
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(data));
ZipParameters parameters = new ZipParameters();
parameters.setFileNameInZip("bank.zip");
new ZipFile("F:\\ssd\\bank.zip").addStream(new ByteArrayInputStream(data), parameters);
}