I am trying to compress a large string object. This is what i tried, but i am unable to understand how to get compressed data, and how to define different type of compression tools.
This is what i got from Android docs.
byte[] input = jsonArray.getBytes("UTF-8");
byte[] output = new byte[100];
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
int compressedDataLength = compresser.deflate(output);
compresser.end();
compresser.deflate(output) gives me a int number, 100
but i am unable to understand which method will give me the compressed output that i can send to service.
The algorithm that I compress my data with is Huffman. You can find it by a simple search. But in your case maybe it helps you:
public static byte[] compress(String data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(data.getBytes());
gzip.close();
byte[] compressed = bos.toByteArray();
bos.close();
return compressed;
}
And to decompress it you can use:
public static String decompress(byte[] compressed) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(bis);
BufferedReader br = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
gis.close();
bis.close();
return sb.toString();
}
The documentation for Deflator shows that the output gets put into the buffer output
try {
// Encode a String into bytes
String inputString = "blahblahblah";
byte[] input = inputString.getBytes("UTF-8");
// Compress the bytes
byte[] output = new byte[100];
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
int compressedDataLength = compresser.deflate(output);
compresser.end();
// Decompress the bytes
Inflater decompresser = new Inflater();
decompresser.setInput(output, 0, compressedDataLength);
byte[] result = new byte[100];
int resultLength = decompresser.inflate(result);
decompresser.end();
// Decode the bytes into a String
String outputString = new String(result, 0, resultLength, "UTF-8");
} catch(java.io.UnsupportedEncodingException ex) {
// handle
} catch (java.util.zip.DataFormatException ex) {
// handle
}
all code you need to ENCODE, COMPRESS , DECOMPRESS , DECODE
Related
I'm trying to store an audio file that is picked by the user from his own music player into sqlite database and I want to know is there a way to convert audio files to byte array.
String path = ""; // Audio File path
InputStream inputStream = new FileInputStream(path);
byte[] arr = readByte(inputStream);
Log.d("byte: ", "" + Arrays.toString(arr));
or
public static byte[] getBytesFromInputStream(InputStream is) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[0xFFFF];
for (int len = is.read(buffer); len != -1; len = is.read(buffer)) {
os.write(buffer, 0, len);
}
return os.toByteArray();
}
try {
String path = ""; // Audio File path
InputStream inputStream = new FileInputStream(path);
byte[] myByteArray = getBytesFromInputStream(inputStream);
// ...
} catch(IOException e) {
// Handle error...
}
I tried to encrypt plaintext using the below code. The code seems encrypt the text but it doesnt decrypt to plaintext back. What am I doing wrong ?
The code:
Entity entity = new Entity("password");
byte[] ciphertext = crypto.encrypt(("data to encrypt").getBytes(),entity);
plaintext = crypto.decrypt(ciphertext,entity)
Output:
Ecrypted text:[B#417a110
Decrypted text:[B#417df20
The following code can encrypt/decrypt string
KeyChain keyChain = new SharedPrefsBackedKeyChain(context, CryptoConfig.KEY_256);
crypto = AndroidConceal.get().createDefaultCrypto(keyChain);
public static String encrypt(String key, String value) throws KeyChainException, CryptoInitializationException, IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
OutputStream cryptoStream = crypto.getCipherOutputStream(bout, Entity.create(key));
cryptoStream.write(value.getBytes("UTF-8"));
cryptoStream.close();
String result = Base64.encodeToString(bout.toByteArray(), Base64.DEFAULT);
bout.close();
return result;
}
public static String decrypt(String key, String value) throws KeyChainException, CryptoInitializationException, IOException {
ByteArrayInputStream bin = new ByteArrayInputStream(Base64.decode(value, Base64.DEFAULT));
InputStream cryptoStream = crypto.getCipherInputStream(bin, Entity.create(key));
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int read = 0;
byte[] buffer = new byte[1024];
while ((read = cryptoStream.read(buffer)) != -1) {
bout.write(buffer, 0, read);
}
cryptoStream.close();
String result = new String(bout.toByteArray(), "UTF-8");
bin.close();
bout.close();
return result;
}
I have found the answer.
The reason is we were printing the byte array instead of the String.
The array is going to comprise of a set of bytes so that's what we saw when we printed them out in the logcat.
To see the actual String, we just need to put the byte[] into a new String(byte[]) - this is taken from the official facebook examples with my modifications:
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(getActivity()),
new SystemNativeCryptoLibrary());
if (!crypto.isAvailable()) {
Log.e("Crypto","Crypto is missing");
}
String password = "Password";
Entity entity = new Entity("TEST");
byte[] encryptedPass = new byte[0];
byte[] b = password.getBytes(Charset.forName("UTF-8"));
try {
encryptedPass = crypto.encrypt(b, entity);
Log.e("Crypto Encrypted", new String(encryptedPass));
byte[] decryptedPass = crypto.decrypt(encryptedPass, entity);
Log.e("Crypto Decrypted ", new String(decryptedPass));
} catch (KeyChainException e) {
e.printStackTrace();
} catch (CryptoInitializationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Results:
08-02 19:31:11.237 29364-29364/? E/Crypto Encrypted﹕
0��&�?B�6���H���`��"�1��xx� 08-02 19:31:11.237 29364-29364/?
E/Crypto Decrypted﹕ Password
Base64.encodeToString(cipherText, Base64.DEFAULT); then store it.
It might be a little too late but I had the same issue and managed to get the plain text after the decryption.
What you really need to do is to use ByteArrayOutputStream like the following code:
Entity entity = new Entity("password");
byte[] ciphertext = crypto.encrypt(("data to encrypt").getBytes(),entity);
byte[] plainText = crypto.decrypt(ciphertext,entity);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(plainText, 0, plainText.length);
String decryptedPassword = out.toString();
out.close();
Hope this helps.
I am trying to convert the captured photos (in .jpeg format ) to hexadecimal strings but when it comes to action, it tales more than 2 minutes to return the successful conversion. Would you please tell me how to enhance the performance besides increasing the buffer size? (using in Android)
The below is my code
private String changeByteToHex(byte[] a) {
StringBuilder sb = new StringBuilder();
for (byte d : a) {
sb.append(String.format("%02X", d));
}
return sb.toString();
}
public String photoEncode(File file) {
try{
ByteArrayInputStream inStream = retrieveByteArrayInputStream(file);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] temp = new byte[8192];
int read;
while((read = inStream.read(temp)) >= 0){
outStream.write(temp, 0, read);
}
byte[] data = outStream.toByteArray();
return changeByteToHex(data);
} catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
I am looking for the most efficient way of converting image file to Base64 String in Android.
The image has to be sent in a single Base64 String at once to backend.
First I use imageToByteArray and then imageToBase64 to get the String.
public static byte[] imageToByteArray(String ImageName) throws IOException {
File file = new File(sdcard, ImageName);
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
//Close input stream
is.close();
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
return bytes;
}
public String imageToBase64(String ImageName){
String encodedImage = null;
try {
encodedImage = Base64.encodeToString(imageToByteArray(ImageName), Base64.DEFAULT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encodedImage;
}
Below is how I handle it mostly, this is in the gotActivityResults callback after calling the image picker activity. It's similar to your's but I think it will be more efficient because the toByteArray from the stream is native c code behind it as opposed to the java loop in yours.
Uri selectedImage = imageReturnedIntent.getData();
InputStream imageStream = getContentResolver().openInputStream(selectedImage);
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
yourSelectedImage.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte [] ba = bao.toByteArray();
String ba1= Base64.encodeToString(ba, 0);
HashMap<String, String > params = new HashMap<String, String>();
params.put("avatar", ba1);
params.put("id", String.valueOf(uc.user_id));
params.put("user_id", String .valueOf(uc.user_id));
params.put("login_token", uc.auth_token);
uc.setAvatar(params);
I have cheerapp.wav or cheerapp.mp3 or some other format.
InputStream in = context.getResources().openRawResource(R.raw.cheerapp);
BufferedInputStream bis = new BufferedInputStream(in, 8000);
// Create a DataInputStream to read the audio data from the saved file
DataInputStream dis = new DataInputStream(bis);
byte[] music = null;
music = new byte[??];
int i = 0; // Read the file into the "music" array
while (dis.available() > 0) {
// dis.read(music[i]); // This assignment does not reverse the order
music[i]=dis.readByte();
i++;
}
dis.close();
For the music byte array which takes the data from the DataInputStream. I don't know what the length of that to allocate.
This is raw file from resource not a file therefore I wouldn't know the size of that thing.
You do have byte array length as you can see:
InputStream inStream = context.getResources().openRawResource(R.raw.cheerapp);
byte[] music = new byte[inStream.available()];
And then you can read whole Stream into byte array easily.
Of course I would recommend that you do check when it comes to the size and use ByteArrayOutputStream with smaller byte[] buffer if needed:
public static byte[] convertStreamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[10240];
int i = Integer.MAX_VALUE;
while ((i = is.read(buff, 0, buff.length)) > 0) {
baos.write(buff, 0, i);
}
return baos.toByteArray(); // be sure to close InputStream in calling function
}
If you'll be doing lots of IO operations I recommend that you make use of org.apache.commons.io.IOUtils. That way you won't need to worry too much about quality of your IO implementation and once you import JAR into your project you would just do:
byte[] payload = IOUtils.toByteArray(context.getResources().openRawResource(R.raw.cheerapp));
Hope it will help.
Create an sdcard path:
String outputFile =
Environment.getExternalStorageDirectory().getAbsolutePath() + "/recording.3gp";
Convert as a file and have to call the byte array method:
byte[] soundBytes;
try {
InputStream inputStream =
getContentResolver().openInputStream(Uri.fromFile(new File(outputFile)));
soundBytes = new byte[inputStream.available()];
soundBytes = toByteArray(inputStream);
Toast.makeText(this, "Recordin Finished"+ " " + soundBytes, Toast.LENGTH_LONG).show();
} catch(Exception e) {
e.printStackTrace();
}
method:
public byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int read = 0;
byte[] buffer = new byte[1024];
while (read != -1) {
read = in.read(buffer);
if (read != -1)
out.write(buffer,0,read);
}
out.close();
return out.toByteArray();
}
In Kotlin use
InputStream.readBytes()