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.
Related
I want to use java(httpurlconnection class) to download a pdf file,but have some thing puzzle,the core code is:
BufferedInputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
OutputStream output = new FileOutputStream("F:/httpclient-tutorial.pdf");
byte[] infoBytes = new byte[BUFFER];
while(inputStream.read(infoBytes) != -1){
output.write(infoBytes, 0, BUFFER);
}
Question:when the BUFFER is 1024,get the pdf file is larger than real one;but the BUFFER is 8,then it's ok. I don't know why it is? Has anyone know about that?
You're unconditionally writing out the whole of the buffer on each iteration. You should only write out as many bytes as you've just read:
int bytesRead;
while((bytesRead = inputStream.read(infoBytes)) != -1){
output.write(infoBytes, 0, bytesRead);
}
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)
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() );
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);
I have a FileInputStream created using Context.openFileInput(). I now want to convert the file into a byte array.
Unfortunately, I can't determine the size of the byte array required for FileInputStream.read(byte[]). The available() method doesn't work, and I can't create a File to check it's length using the specific pathname, probably because the path is inaccessible to non-root users.
I read about ByteArrayOutputStream, and it seems to dynamically adjust the byte array size to fit, but I can't get how to read from the FileInputStream to write to the ByteArrayOutputStream.
This should work.
InputStream is = Context.openFileInput(someFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((int bytesRead = is.read(b)) != -1) {
bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
This is the easiest way
FileInputStream fis = openFileInput(fileName);
byte[] buffer = new byte[(int) fis.getChannel().size()];
fis.read(buffer);
You can pre-allocate the byte array using
int size = context.getFileStreamPath(filename).length();
This way, you will avoid allocating memory chunks every time your ByteArrayOutputStream fills up.
For the method to work on any device and aplication you just need to replace:
InputStream is = Context.getContentResolver().openInputStream(yourFileURi);
This way you can encode external files as well.