Android - 从 Uri 到 InputStream 再到字节数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2436385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:51:01  来源:igfitidea点击:

Android - getting from a Uri to an InputStream to a byte array?

android

提问by AP257

I'm trying to get from an Android Uri to a byte array.

我正在尝试从 Android Uri 获取字节数组。

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 stringinto a byte array, rather than the file :(

我有以下代码,但它一直告诉我字节数组长 61 个字节,即使文件很大 - 所以我认为它可能将 Uri字符串转换为字节数组,而不是文件:(

  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".

输出为“fileUriString = content://media/external/video/media/53”和“数据长度为 61 字节”。

Thanks!

谢谢!

回答by brabster

is.toString()will give you a String representation of the InputStream instance, not its content.

is.toString()将为您提供 InputStream 实例的 String 表示,而不是其内容。

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.

您需要从 InputStream 中 read() 字节到您的数组中。有两种读取方法可以做到这一点,read()一次读取一个字节,read(byte[] bytes)将字节从 InputStream 读取到您传递给它的字节数组中。



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).

更新:在 InputStream 没有长度的情况下读取字节,您需要读取字节直到没有任何剩余。我建议为自己创建一个像这样的方法是一个很好的简单起点(这至少是我在 Java 中的做法)。

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();
}

回答by AP257

With Apache Commons, you can read all the bytes from a Streamthanks to IOUtils.toByteArray(InputStream)as next:

使用Apache Commons,您可以从Stream感谢中读取所有字节,IOUtils.toByteArray(InputStream)如下所示:

byte[] recordData = IOUtils.toByteArray(inStream);

download jar: http://commons.apache.org/io/download_io.cgi

下载jar:http: //commons.apache.org/io/download_io.cgi

回答by Peter F

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 InputStreamlike buffered, use, and readBytes.

在科特林,他们增加了便捷的扩展功能InputStream一样bufferedusereadBytes

  • buffereddecorates the input stream as BufferedInputStream
  • usehandles closing the stream
  • readBytesdoes the main job of reading the stream and writing into a byte array
  • buffered将输入流装饰为 BufferedInputStream
  • use处理关闭流
  • readBytes主要工作是读取流并写入字节数组

Error cases:

错误案例:

  • IOExceptioncan occur during the process (like in Java)
  • openInputStreamcan return null. If you call the method in Java you can easily oversee this. Think about how you want to handle this case.
  • IOException可能在此过程中发生(如在 Java 中)
  • openInputStream可以返回null。如果您在 Java 中调用该方法,您可以轻松地监督这一点。想想你想如何处理这个案例。

回答by Filippo Mazza

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.

如果流没有可用字节,则这种方式 read 不会阻塞,如本答案所述

回答by Dat Nguyen

With Google Guava, you can use ByteStreams.toByteArray(InputStream)to get all the bytes in the input stream:

使用 Google Guava,您可以使用ByteStreams.toByteArray(InputStream)获取输入流中的所有字节:

InputStream is = ...;
byte[] bytes = ByteStream.toByteArray(is);

回答by user2466053

if You have an Uri, instead of a regular file name, you should use Content Resolver. Android: Getting a file URI from a content URI?

如果你有一个 Uri,而不是一个普通的文件名,你应该使用 Content Resolver。 Android:从内容 URI 中获取文件 URI?

I tried this, and it works. Uri uri; // it is something, I've got from a file chooser. Of course, I must be sure, that the uri points to a filename, and it is not an image, or audio, or something else...

我试过这个,它有效。乌里乌里; // 它是一些东西,我从文件选择器中得到。当然,我必须确定,uri 指向文件名,而不是图像、音频或其他东西......

InputStream is=getContentResolver().openInputStream(uri);
InputStreamReader ir=new InputStreamReader(is);
bu=new BufferedReader(ir);
String s;
while ((s=bu.readLine())!=null){
    //do something with the line...
}
bu.close();

I've omitted some try-catch-finally from the code, but the most important things are here. The first thing is, that if you have an uri, you cannot use the standard file reader.

我从代码中省略了一些 try-catch-finally,但最重要的事情在这里。第一件事是,如果您有 uri,则不能使用标准文件阅读器。

回答by user2374654

Sharing my idea :D

分享我的想法 :D

private static byte[] getStringFromInputStream(InputStream is) 
{

    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();
    byte[] bReturn = new byte[0];

    String line;
    try 
    {

        br = new BufferedReader(new InputStreamReader(is, "Big5"));
        while ((line = br.readLine()) != null) 
        {
            sb.append(line);
        }
        String sContent = sb.toString();
        bReturn = sContent.getBytes();          
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    } 
    finally 
    {
        if (br != null) 
        {
            try 
            {
                br.close();
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    } 
    return bReturn;
}