Android byte array batches - java

I am sending image through Bluetooth pro-grammatically. When i send image as Byte array at the sending side the byte array length is = 83402 and at the receiving side i am getting byte bacthes of 1024.
I want to combine these 1024 batches into single byte array so that i again convert it as an image.
Here in the msg.obj i get 1024 bacth of byte array.
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
Bitmap bmp=BitmapFactory.decodeByteArray(readBuf,0,readBuf.length);
After that i am also getting this warning..
"Default buffer size used in BufferedOutputStream constructor. It would be better to be explicit if an 8k buffer is required"
any help would be appreciated.
Thanks

Should be roughly something like this:
byte[] readBuf = new byte[83402]; // this array will hold the bytes for the image, this value better be not hardcoded in your code
int start = 0;
while(/*read 1024 byte packets...*/) {
readBuf.copyOfRange((byte[]) msg.obj, start, start + 1024); // copy received 1024 bytes
start += 1024; //increment so that we don't overwrite previous bytes
}
/*After everything is read...*/
Bitmap bmp=BitmapFactory.decodeByteArray(readBuf,0,readBuf.length);

I'm going to go out on a limb here and assume you're using the BluetoothChat example from the sdk to build your image sender (all your examples match it). Here's a quick conversion I threw together - may not be the best but it works.
You're getting them in batches of 1024 because in the BluetoothChatService.java run function it creates a buffer array size 1024 that goes and gets info from the input stream. If you create another buffer that will fit the image there (I set a max 1mb) then your run function would have:
byte[] buffer = new byte[1024];
byte[] imgBuffer = new byte[1024*1024];
int pos = 0;
with your pos variable keeping track of where you are in your imgBuffer.
Then you just copy it over while you're getting chunks in the while(true) loop of the image like this (mmInStream is an InputStream):
int bytes = mmInStream.read(buffer);
System.arraycopy(buffer,0,imgBuffer,pos,bytes);
pos += bytes;
I send a message to let it know that the image is done sending and at that point shuttle the imgBuff over to the other thread (pos has the size of the imgBuffer at this point):
mHandler.obtainMessage(BluetoothChat.IMAGE_READ, pos, -1, imgBuffer)
.sendToTarget();
I had defined IMAGE_READ to decode the array like you did in your MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
BitmapFactory.decodeByteArray(readBuf, 0, msg.arg1);

Related

How to extract chunks of information from a ByteBuffer?

I've a ByteBuffer that is populated via socketChannel.read(buffer).
I want to extract information as byte[] or ByteBuffer that's located at specific position in this buffer.
It's being done like this at the moment:
byte[] data = new byte[length];
int oldPos = buffer.position();
buffer.position(offset);
buffer.get(data, 0, length);
buffer.position(oldPos);
I'd like to not create copies every time I want to extract information from the buffer. I've come up with the following approach. Please advise if there's a better way to accomplish this.
ByteBuffer readOnlyuplicate = orig.asReadOnlyBuffer();
readOnlyuplicate.position(start);
readOnlyuplicate.limit(start + length - 1);

Optimization of rewriting from AudioInputStream to ByteArrayOutputStream

There were few similar topics on stackoverflow but none of them seemed good enough for me. The problem is i have such a snippet of code:
// AudioInputStream in;
final int BUFFER_SIZE = 8192;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[BUFFER_SIZE];
int bytesRead = 0;
while ((bytesRead = in.read(byteBuffer, 0, BUFFER_SIZE)) != -1) {
byteStream.write(byteBuffer, 0, bytesRead);
}
byte[] audioData = byteStream.toByteArray();
This code reads data of mp3 file and saves it to byte array, but takes about 10 seconds. Is there any possibility to store whole mp3 data into buffer in shorter time?
I've tried to avoid passing the size of buffer or extend it but that caused additional problems (e.g. file was not read correctly).
Thanks in advance
You are copying data 3 times, you can avoid that by first checking the file size, allocating a byte array big enough, and reading into that directly.
It also helps a little bit to pre-allocate space in the ByteArrayOutputStream so it doesn't have to be increased in size many times.
If you can't get the file size up front, you can allocate a new byte[] for every block, and put them in a list, until you got them all. Then allocate the final array and copy all of them into the last array. IF you need a byte[] in the end. If you don't, there may be more efficient ways to proceed.

ByteArrayOutputStream.toString() generating extra characters

I have the following code:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int size = 4096;
byte[] bytes = new byte[size];
while (is.read(bytes, 0, size) != -1)
{
baos.write(bytes);
baos.flush();
}
When I do:
String s = baos.toString();
I get \u0000-s appended to my string. So, if my character data is only X bytes out of Y, the Y-Z will get prefilled with \u0000 making it impossible to check for equals. What am I doing wrong here? How should I be converting the bytes to a String in this case?
The entire array (all 4096 bytes) is be written to the output - arrays have no idea of how much "useful data" they contain!
Store how much was read into a variable (InputStream.read returns a useful number) and specify that to the appropriate OutputStream.write overload to only write a portion (that which contains the useful data) of the array.
While the above change should "fix" the problem, it is generally recommended to use the string<->byte[] conversion forms that take in an explicit character set.
You should only be writing as much data as you are reading in each time through the loop:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int size;
byte[] bytes = new byte[4096];
while (size = is.read(bytes, 0, bytes.length) != -1)
{
baos.write(bytes, 0, size);
}
baos.flush();
String s = baos.toString();
You might consider specifying a specific character set for converting the bytes to a String. The no-arg toString() method uses the platform default encoding.
new String(baos.toByteArray(), 0, strLen, encoding)

Create a ArrayList of byte Array in Android

I want to read bytes from httpresponse coming from server continuosly into an array.
I'm creating a byte array with a maximum size of 2048.
So, I wanted to create a dynamically increasing array and I found that ArrayList is the solution.
How can i overcome this solution?
Any help would be appreciated lot
You can use a ByteArrayOutputStream to accumulate the bytes as you read them from the server. I would not use an ArrayList<Byte> because it requires boxing every byte value in a Byte.
When you want to access the bytes that have been accumulated, just call toByteArray() on the ByteArrayOutputStream.
You can have an array of byte like:
List<Byte> arrays = new ArrayList<Byte>();
To convert it back to arrays
Byte[] soundBytes = arrays.toArray(new Byte[arrays.size()]);
- You can also use ByteArrayInputStream and ByteArrayOutputStream.
Eg:
InputStream inputStream = socket.getInputStream();
// read from the stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] content = new byte[ 2048 ];
int bytesRead = -1;
while( ( bytesRead = inputStream.read( content ) ) != -1 ) {
baos.write( content, 0, bytesRead );
} // while
// now, as you have baos in hand, I don't think you still need a bais instance
// but, to make it complete,
// now you can generate byte array input stream as below
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );

Java: Is there a way to get the expected uncompressed length of a zipped byte array?

I'm using java.util.zip to compress and uncompress byte arrays, using Inflater and Deflater.
Does the compressed result contain information about the expected length of the original data or do I have to store it myself?
I would like to know the expected length of the uncompressed information without uncompressing all of the data.
If you just compress and decompress byte arrays - without storing them in a ZipEntry - you must save the size yourself, as the byte array to which you compress the data is not necessarily used to its full extent.
You can see this clearly from the example in Deflater's javadoc:
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);
// 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
}
The code must maintain the compressed data's lenght as the output array is of length 100, no matter the actual length of the data it stores.

Categories