I am deflating a string with java with this function:
protected static byte[] Compress(String source) {
try {
// deficne start time
long startTime = System.currentTimeMillis();
//get bytes
byte[] bytes = source.getBytes("UTF-8");
Deflater deflater = new Deflater();
deflater.setInput(bytes);
deflater.finish();
ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length);
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int bytesCompressed = deflater.deflate(buffer);
bos.write(buffer, 0, bytesCompressed);
}
try {
//close the output stream
bos.close();
} catch (IOException ioe) {
System.out.println("Error while closing the stream : " + ioe);
}
//get the compressed byte array from output stream
byte[] compressedArray = bos.toByteArray();
return compressedArray;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
now, I want to inflate that string with PHP with this function:
$uncompressed = gzinflate($filepath);
echo $uncompressed;
die();
but I got data error in php file, how can I solve this problem?
the error message is :
Warning: gzinflate(): data error
regards
Related
I have a raw string which is base64 compressed with zlib coming from the server and I need to convert it into JSON using zlib decompression. Here is the code I am using:
public static void decompress(String compressed) throws Exception {
try {
Inflater inflater = new Inflater(true);
inflater.setInput(compressed.getBytes());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(compressed.getBytes().length);
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
String str = new String(output, StandardCharsets.UTF_8);
Logger.e("STR", str);
} catch (Exception e) {
e.printStackTrace();
}
}
However, I am getting this error while decompressing:
java.util.zip.DataFormatException: invalid code lengths set
at line int count = inflater.inflate(buffer);
I don't understand what I am doing wrong. Please help me fix this issue.
I'm trying (In Java) to get a file document then convert it to bitArray afterwards to a String of similar representation, then back to the original bit array and finally to the original final document.
Here is my code, But the file generated is not viewable in this case the image.
try {
File file = new File("C:/Users/dkimigho/Downloads/kenyapowerlogo.jpg");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//create FileInputStream which obtains input bytes from a file in a file system
//FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
//Writes to this byte array output stream
bos.write(buf, 0, readNum);
System.out.println("read " + readNum + " bytes,");
}
} catch (IOException ex) {
Logger.getLogger(ARRAYBITStoPDF.class.getName()).log(Level.SEVERE, null, ex);
}
byte[] bytes = bos.toByteArray();
System.out.println("byte1");
for (int i = 0; i < bytes.length; i++) {
System.out.print(bytes[i]);
}
//We have the bytes now convert to String
String stringbytearray=new String(bytes);
System.out.println("stringbytearray: "+stringbytearray);
//We have the bytes now convert to String
byte[] content = stringbytearray.getBytes();
System.out.println("byte2");
for (int i = 0; i < content.length; i++) {
System.out.print(content[i]);
}
int size = bytes.length;
InputStream isfilecontent = null;
byte[] b = new byte[size];
isfilecontent = new ByteArrayInputStream(content);
//writing the downloaded data into a PDF file
FileOutputStream fileOutputpdf = new FileOutputStream("C:/Users/dkimigho/Downloads/mykenyapowerlogo.jpg");
/* use binary I/O to prevent line based operation messing with the encoding.*/
byte[] buf2 = new byte[2048];
int b_read = 0;
while ( (b_read = isfilecontent.read(buf2)) > 0) {
fileOutputpdf.write(buf2, 0, b_read);
}
fileOutputpdf.flush();
//closed the output stream
fileOutputpdf.close();
} catch (IOException e) {
// handle IOException
System.out.println(e.getMessage());
}
Any help on pointing what I'm doing wrong? A correction of my code to a working one may be important.
I found an answer one has to use JAVA 8 java.util.Base64 to encode and decode the bytes without loosing information on the document. I hope it will be of help to someone.
/*
* 1. How to convert an image file to byte array?
*/
try {
File file = new File("C:/Users/qwerty/Downloads/factura.pdf");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//create FileInputStream which obtains input bytes from a file in a file system
//FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
//Writes to this byte array output stream
bos.write(buf, 0, readNum);
// System.out.println("read " + readNum + " bytes,");
}
} catch (IOException ex) {
Logger.getLogger(ARRAYBITStoPDF.class.getName()).log(Level.SEVERE, null, ex);
}
byte[] bytes = bos.toByteArray();
bos.close(); // should be inside a finally block
//We have the bytes now convert to String
// ENCODING
String encodedDoc= Base64.getEncoder().encodeToString(bytes);
System.out.println(encodedDoc);
// DECODING
int size = bytes.length;
InputStream isfilecontent = null;
//byte[] b = new byte[size];
isfilecontent = new ByteArrayInputStream(Base64.getDecoder().decode(encodedDoc));
//writing the downloaded data into a PDF file
FileOutputStream fileOutputpdf = new FileOutputStream("C:/Users/qwerty/Downloads/myfactura.pdf");
/* use binary I/O to prevent line based operation messing with the encoding.*/
byte[] buf2 = new byte[2048];
int b_read = 0;
while ( (b_read = isfilecontent.read(buf2)) > 0) {
fileOutputpdf.write(buf2, 0, b_read);
}
fileOutputpdf.flush();
//closed the output stream
fileOutputpdf.close();
} catch (IOException e) {
// handle IOException
System.out.println(e.getMessage());
}
We have a requirement to send a saml request to IDP.The request should be deflated ,base64 & URL encoded.Below is the code for deflate the request.
byte[] encodedArray=IDPUtil.compress(samlRequest.getBytes());
public static byte[] compress(byte[] data){
byte[] output = null;
try {
Deflater deflater = new Deflater();
deflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
deflater.finish();
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int count = deflater.deflate(buffer);
outputStream.write(buffer, 0, count);
output = outputStream.toByteArray();
System.out.println("Original: " + data.length / 1024 + " Kb");
System.out.println("Compressed: " + output.length / 1024 + " Kb");
}
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return output;
}
In the IDP end while inflating we are getting the below exception
java.util.zip.DataFormatException: invalid bit length repeat
at java.util.zip.Inflater.inflateBytes(Native Method)
at java.util.zip.Inflater.inflate(Inflater.java:238)
Below is the decompression logic
String urlDecodedString=URLDecoder.decode(urlEncodedString,"UTF-8");
byte[] base64DecodedArray=base64.decode(urlDecodedString);
System.out.println(new String(decompress(base64DecodedArray)));
public static byte[] decompress(byte[] data){
System.out.println("Length : "+data.length/1024 + "KB");
byte[] output = null ;
Inflater inflater = new Inflater();
inflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
byte[] buffer = new byte[1024];
try {
while (!inflater.finished()) {
int count;
count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
output = outputStream.toByteArray();
} catch (DataFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return output;
}
Please suggest what went here ?
I'm trying to compress the byte data from video, the app crashes when the file is over 10mb due to the limitations of Parse servers. So I'm trying to compress at 10mb. The code does well on older phones but on the newer phones the the video bytes easily go over 10mb but the code won't compress the bytes down to 10 mb. Is there something I can add or something?
private void uploadVideo() {
Intent videoIntent = new Intent (MediaStore.ACTION_VIDEO_CAPTURE);
mMediaUri = getOutputMediaFileUri (MEDIA_TYPE_VIDEO);
if (mMediaUri == null) {
// display an error
Toast.makeText (MemberActivity.this, R.string.error_external_storage,
Toast.LENGTH_LONG).show ();
} else {
videoIntent.putExtra (MediaStore.EXTRA_OUTPUT, mMediaUri);
videoIntent.putExtra (MediaStore.EXTRA_DURATION_LIMIT, 10);
videoIntent.putExtra (MediaStore.EXTRA_SIZE_LIMIT, 1024*1024*10);
videoIntent.putExtra (MediaStore.EXTRA_VIDEO_QUALITY, 0); // 0 = lowest res
startActivityForResult (videoIntent, CAMERA_CAPTURE_VIDEO_REQUEST_CODE);
}
String mediaBytes = mMediaUri.getEncodedPath ();
//Set up video file and data
File iFile = new File (mediaBytes);
byte[] byteArray = new byte[(int) iFile.length ()];
try {
FileInputStream fileInputStream = new FileInputStream (iFile);
fileInputStream.read (byteArray);
for (byte aByteArray : byteArray) {
System.out.print ((char) aByteArray);
}
} catch (FileNotFoundException e) {
System.out.println ("File Not Found.");
e.printStackTrace ();
} catch (IOException e1) {
System.out.println ("Error Reading The File.");
e1.printStackTrace ();
}
final ParseFile file = new ParseFile ("HipkuVideo.mp4", byteArray);
file.saveInBackground (new SaveCallback () {
#Override
public void done(ParseException e) {
if (e == null) {
//addPhotoTransferToUserUpload (file);
// Show a simple toast message
Toast.makeText (MemberActivity.this, "Saving to SD Card",
Toast.LENGTH_SHORT).show ();
} else {
// Show a simple toast message
Toast.makeText (MemberActivity.this, "Error saving:" + e.getMessage (),
Toast.LENGTH_SHORT).show ();
}
and here is the compress code:
public static byte[] getByteArrayFromFile(Context context, Uri uri) {
byte[] fileBytes = null;
InputStream inStream = null;
ByteArrayOutputStream outStream = null;
if (uri.getScheme().equals("content")) {
try {
inStream = context.getContentResolver().openInputStream(uri);
outStream = new ByteArrayOutputStream();
// Compressor with highest level of compression
Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_COMPRESSION);
// Give the compressor the data to compress
compressor.setInput(fileBytes);
compressor.finish();
// Create an expandable byte array to hold the compressed data.
// It is not necessary that the compressed data will be smaller than
// the uncompressed data.
outStream = new ByteArrayOutputStream(fileBytes.length);
// Compress the data
byte[] buf = new byte[1024*1024*10];
while (!compressor.finished()) {
int count = compressor.deflate(buf);
outStream.write(buf, 0, count);
}
try {
outStream.close();
} catch (IOException e) {
}
// Get the compressed data
byte[] compressedData = outStream.toByteArray();
byte[] bytesFromFile = new byte[1024]; // buffer size (1 MB)
int bytesRead = inStream.read(compressedData);
while (bytesRead != -1) {
outStream.write(compressedData, 0, bytesRead);
bytesRead = inStream.read(compressedData);
}
fileBytes = outStream.toByteArray();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
finally {
try {
inStream.close();
outStream.close();
}
catch (IOException e) { /*( Intentionally blank */ }
}
}
else {
try {
File file = new File(uri.getPath());
FileInputStream fileInput = new FileInputStream(file);
fileBytes = IOUtils.toByteArray(fileInput);
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
return fileBytes;
}
If you need to compress further than what's provided by ZLIB, take a look at Apache Commons Compress. Specifically, the section on XZ since that uses the LZMA compression algorithm which at it's highest level gives some of the best compression ratios around. Be sure to thoroughly test performance however since it can get a little slow. If you're worried about space you can cut out the Apache middleman and go straight to the Tukaani java library for the same.
In my application I get a profile picture for user then I save it to a serialized class as string.
I do the GZIP compress and Base64 using the code below, but I can not do the reverse thing as you see in the getProfilePicture() method further down:
private void saveBitmap(){
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String bitmapContent = "";
try {
bitmapContent = FileHelpers.compressAndBase64(byteArray);
//later save it...
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Error converting bitmap to gzip and base64");
}
}
public static String compressAndBase64(byte[] byteArray)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream zos = new GZIPOutputStream(baos);
zos.write(byteArray);
zos.close();
byte[] bytes = baos.toByteArray();
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
Now I want to convert it back to Bitmap...but so far I didn't succeed to.
The steps are decoding back the string from Base64 to byte array then decompress the byte array and convert to Bitmap.
public Bitmap getProfilePicture(){
if(getProfilePhotoBase64() != null) {
byte[] decoded = Base64.decode(mProfilePhotoBase64.getBytes(), Base64.DEFAULT);
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(decoded);
GZIPInputStream gis = null;
try {
gis = new GZIPInputStream(is, BUFFER_SIZE);
} catch (IOException e) {
e.printStackTrace();
}
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
try {
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
} catch (IOException e) {
e.printStackTrace();
}
try {
gis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray = string.toString().getBytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0,byteArray.length);
if(bitmap != null) {
return bitmap;
} else {
return null;
}
}
return null;
}
This is the error message I get using the code above:
--- SkImageDecoder::Factory returned null
I can do this quite easy in PHP, but its darn hard to make it work in Java!
if(isset($_POST["photo"])) {
$photoContent = $_POST["photo"];
$photo = imap_base64 ($photoContent);
$photo = gzdecode($photo);
$filename = $_POST["username"].".png";
$dir = SITE_ROOT_PATH."/images/".$user."/".$filename;
file_force_contents($dir, $photo);
} else {
$filename = "NO_PROFILE_PHOTO";
}
Ok I managed to fix the problem in this way:
/**
* IMPORTANT NOTE!!!!!!!!!!!!!!
* String is first converted to byte array, then compressed using GZIP and then
* the resulting byte array is encoded to Base64.DEFAULT
* #return
*/
public String getProfilePhotoBase64() {
return mProfilePhotoBase64;
}
public Bitmap getProfilePicture(){
if(getProfilePhotoBase64() != null) {
byte[] decoded = Base64.decode(mProfilePhotoBase64.getBytes(), Base64.DEFAULT);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(decoded);
GZIPInputStream zis = null;
try {
zis = new GZIPInputStream(bis);
byte[] tmpBuffer = new byte[256];
int n;
while ((n = zis.read(tmpBuffer)) >= 0) {
bos.write(tmpBuffer, 0, n);
}
zis.close();
} catch (IOException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeByteArray(bos.toByteArray(), 0
, bos.toByteArray().length);
if(bitmap != null) {
return bitmap;
} else {
return null;
}
}
return null;
}
And what is the problem exactly? compressAndBase64() will return an empty string as boas.toByteArray() will return 0 bytes as boas is just created and hence empty. You don't need to create a boas. Just change
return Base64.encodeToString(bytes, Base64.DEFAULT);
to
return Base64.encodeToString(byteArray, Base64.DEFAULT);