图像URI转换为字节数组

63

我现在有两个活动。一个从SD卡中提取图像,另一个用于蓝牙连接。

我已经利用Bundle传递了第一个活动中图像的Uri。

现在我希望在蓝牙活动中获取该Uri并将其转换为可通过字节数组传输的状态。我已经看过一些示例,但似乎无法使它们适用于我的代码!!

Bundle goTobluetooth = getIntent().getExtras();
    test = goTobluetooth.getString("ImageUri");

这是我需要拖过来的东西。下一步应该是什么?

9个回答

119

我通过使用 Uri 实现以下操作以获取 byte[]

InputStream iStream =   getContentResolver().openInputStream(uri);
byte[] inputData = getBytes(iStream);

getBytes(InputStream) 方法是:

public byte[] getBytes(InputStream inputStream) throws IOException {
      ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
      int bufferSize = 1024;
      byte[] buffer = new byte[bufferSize];

      int len = 0;
      while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
      }
      return byteBuffer.toByteArray();
    }

仍然出现错误,提示uri无法解析为变量!! - user1314243
1
你需要写下这行代码:InputStream iStream = getContentResolver().openInputStream(Uri.parse(test)); - user370305
我现在只需要让字节数组在传输阶段正常工作。它以前用于发送文本消息,现在需要将其更改为刚刚创建的数组: Thread.sleep(1000); OutputStream outStream; outStream = BT_Socket.getOutputStream(); byte[] ByteArray = ; outStream.write(ByteArray); outStream.flush(); Thread.sleep(1500); - user1314243
我只需要将字节数组放入我上面提到的传输代码中。当我尝试在byte[] ByteArray = inputdata;等中包含它时,它总是出现错误。 - user1314243
3
InputStream iStream =... 这一行代码出现了 FileNotFoundException 异常。 - mrid
显示剩余6条评论

27

Kotlin在这里非常简洁:

@Throws(IOException::class)
private fun readBytes(context: Context, uri: Uri): ByteArray? = 
    context.contentResolver.openInputStream(uri)?.use { it.buffered().readBytes() }

Kotlin为InputStream提供了方便的扩展函数,如buffered、use和readBytes。
- buffered将输入流装饰成BufferedInputStream - use处理流的关闭 - readBytes完成读取流并写入字节数组的主要任务
错误情况:
- 在处理过程中可能会出现IOException(与Java类似) - openInputStream可能返回null。如果在Java中调用该方法,很容易忽视这一点。请考虑如何处理这种情况。

3
我认为最好使用context.contentResolver.openInputStream(uri)?.use { it.buffered().readBytes() },这样即使缓冲区出现问题(虽然不太可能),您也可以确保流被关闭。 - rtsketo
@rtsketo 我同意你的建议。我已经相应地更新了答案。谢谢! - Peter F
@rtsketo 我同意你的建议。我已经相应地更新了答案。谢谢! - undefined

9

Kotlin中的语法

val inputData = contentResolver.openInputStream(uri)?.readBytes()

1
这不是完全正确的,你需要在读取后始终关闭 openInputStream(..)。你可以使用 use { } 来自动关闭它。请查看 Peter 的答案 - rtsketo

5

Java最佳实践:永远不要忘记关闭你打开的每一个流! 这是我的实现:

/**
 * get bytes array from Uri.
 * 
 * @param context current context.
 * @param uri uri fo the file to read.
 * @return a bytes array.
 * @throws IOException
 */
public static byte[] getBytes(Context context, Uri uri) throws IOException {
    InputStream iStream = context.getContentResolver().openInputStream(uri);
    try {
        return getBytes(iStream);
    } finally {
        // close the stream
        try {
            iStream.close();
        } catch (IOException ignored) { /* do nothing */ }
    }
}



 /**
 * get bytes from input stream.
 *
 * @param inputStream inputStream.
 * @return byte array read from the inputStream.
 * @throws IOException
 */
public static byte[] getBytes(InputStream inputStream) throws IOException {

    byte[] bytesResult = null;
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];
    try {
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }
        bytesResult = byteBuffer.toByteArray();
    } finally {
        // close the stream
        try{ byteBuffer.close(); } catch (IOException ignored){ /* do nothing */ }
    }
    return bytesResult;
}

1
使用getContentResolver().openInputStream(uri)从URI获取一个InputStream,然后从该inputstream读取数据并将数据转换为byte[]。
可以尝试以下代码:
public byte[] readBytes(Uri uri) throws IOException {
          // this dynamically extends to take the bytes you read
        InputStream inputStream = getContentResolver().openInputStream(uri);
          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();
        }

请参考此链接


14
你的答案和我的有什么不同? - user370305
方法的名称 :) - Yehor Hromadskyi

0
public void uriToByteArray(String uri)
    {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File(uri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        byte[] buf = new byte[1024];
        int n;
        try {
            while (-1 != (n = fis.read(buf)))
                baos.write(buf, 0, n);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = baos.toByteArray();
    }

0
使用以下方法在Android Studio中从URI创建一个bytesArray:

使用以下方法在Android Studio中从URI创建一个bytesArray

public byte[] getBytesArrayFromURI(Uri uri) {
    try {
        InputStream inputStream = getContentResolver().openInputStream(uri);
        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];

        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }

        return byteBuffer.toByteArray();

    }catch(Exception e) {
        Log.d("exception", "Oops! Something went wrong.");
    }
    return null;
}

0

这段代码对我有效

Uri selectedImage = imageUri;
            getContentResolver().notifyChange(selectedImage, null);
            ImageView imageView = (ImageView) findViewById(R.id.imageView1);
            ContentResolver cr = getContentResolver();
            Bitmap bitmap;
            try {
                 bitmap = android.provider.MediaStore.Images.Media
                 .getBitmap(cr, selectedImage);

                imageView.setImageBitmap(bitmap);
                Toast.makeText(this, selectedImage.toString(),
                        Toast.LENGTH_LONG).show();
                finish();
            } catch (Exception e) {
                Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT)
                        .show();

                e.printStackTrace();
            }

0
一个解决方案,它可以关闭字节流并管理您的内存:
fun Uri.readBytes(context: Context): ByteArray? {
    var inputStream          : InputStream? = null
    var byteArrayOutputStream: ByteArrayOutputStream? = null

    try {
        inputStream           = context.contentResolver.openInputStream(this)
        byteArrayOutputStream = ByteArrayOutputStream()

        if (inputStream != null) {
            val buffer = ByteArray(1024)
            var bytesRead: Int

            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead)
            }

            return byteArrayOutputStream.toByteArray()
        }
    } catch (e: IOException) {
        e.printStackTrace()
    } finally {
        inputStream?.close()
        byteArrayOutputStream?.close()
    }

    return null
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接