Android - getting from a Uri to an InputStream to a byte array?
I'm trying to get from an Android Uri to a byte array.
I have the following code, but it keeps telling me that the byte array is 61 bytes long, even though the file is quite large - so I think it may be turning the Uri string into a byte array, rather than the file :(
Log.d(LOG_TAG, "fileUriString = " + fileUriString);
Uri tempuri = Uri.parse(fileUriString);
InputStream is = cR.openInputStream(tempuri);
String str=is.toString();
byte[] b3=str.getBytes();
Log.d(LOG_TAG, "len of data is " + imageByteArray.length
+ " bytes");
Please can someone help me work out what to do?
The output is "fileUriString = content://media/external/video/media/53" and "len of data is 61 bytes".
Thanks!
Solution 1:
is.toString()
will give you a String representation of the InputStream instance, not its content.
You need to read() bytes from the InputStream into your array. There's two read methods to do that, read() which reads a single byte at a time, and read(byte[] bytes) which reads bytes from the InputStream into the byte array you pass to it.
Update: to read the bytes given that an InputStream does not have a length as such, you need to read the bytes until there is nothing left. I suggest creating a method for yourself something like this is a nice simple starting point (this is how I would do it in Java at least).
public byte[] readBytes(InputStream inputStream) throws IOException {
// this dynamically extends to take the bytes you read
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
// this is storage overwritten on each iteration with bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
// we need to know how may bytes were read to write them to the byteBuffer
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
// and then we can return your byte array.
return byteBuffer.toByteArray();
}
Solution 2:
With Apache Commons, you can read all the bytes from a Stream
thanks to IOUtils.toByteArray(InputStream)
as next:
byte[] recordData = IOUtils.toByteArray(inStream);
download jar: http://commons.apache.org/io/download_io.cgi
Solution 3:
Kotlin way:
@Throws(IOException::class)
private fun readBytes(context: Context, uri: Uri): ByteArray? =
context.contentResolver.openInputStream(uri)?.buffered()?.use { it.readBytes() }
In Kotlin, they added convenient extension functions for InputStream
like buffered
, use
, and readBytes
.
-
buffered
decorates the input stream asBufferedInputStream
-
use
handles closing the stream -
readBytes
does the main job of reading the stream and writing into a byte array
Error cases:
-
IOException
can occur during the process (like in Java) -
openInputStream
can returnnull
. If you call the method in Java you can easily oversee this. Think about how you want to handle this case.
Solution 4:
while ((len = inputStream.read(buffer)) != -1)
should be
while (inputStream.available() >0 && (len = inputStream.read(buffer)) != -1)
This way read will not block if stream has no available bytes as explained in this answer.
Solution 5:
With Google Guava, you can use ByteStreams.toByteArray(InputStream)
to get all the bytes in the input stream:
InputStream is = ...;
byte[] bytes = ByteStream.toByteArray(is);