在Java中将InputStream转换为字节数组

1001

我该如何将整个InputStream读入字节数组中?


18
请参考以下链接了解如何将 byte[] 转换为 InputStream:https://dev59.com/questions/AHI95IYBdhLWcg3w7CnL。 - David d C e Freitas
35个回答

1

Java 8的方法(感谢BufferedReaderAdam Bien

private static byte[] readFully(InputStream input) throws IOException {
    try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
        return buffer.lines().collect(Collectors.joining("\n")).getBytes(<charset_can_be_specified>);
    }
}

请注意,此解决方案会擦除回车符 ('\r'),可能不适合。

4
这是关于“String”的。提问者正在询问关于“byte[]”的内容。 - FrozenFire
不仅仅是\r可能会成为问题。该方法将字节转换为字符,然后再次转换为字节(使用InputStreamReader的默认字符集)。任何在默认字符编码中无效的字节(例如,在Linux上对于UTF-8为-1)都将被破坏,甚至可能改变字节数。 - seanf
看起来这是一个不错的答案,但是偏向于文本。买家要小心。 - Wheezil

0

这里有一个经过优化的版本,尽量避免复制数据字节:

private static byte[] loadStream (InputStream stream) throws IOException {
   int available = stream.available();
   int expectedSize = available > 0 ? available : -1;
   return loadStream(stream, expectedSize);
}

private static byte[] loadStream (InputStream stream, int expectedSize) throws IOException {
   int basicBufferSize = 0x4000;
   int initialBufferSize = (expectedSize >= 0) ? expectedSize : basicBufferSize;
   byte[] buf = new byte[initialBufferSize];
   int pos = 0;
   while (true) {
      if (pos == buf.length) {
         int readAhead = -1;
         if (pos == expectedSize) {
            readAhead = stream.read();       // test whether EOF is at expectedSize
            if (readAhead == -1) {
               return buf;
            }
         }
         int newBufferSize = Math.max(2 * buf.length, basicBufferSize);
         buf = Arrays.copyOf(buf, newBufferSize);
         if (readAhead != -1) {
            buf[pos++] = (byte)readAhead;
         }
      }
      int len = stream.read(buf, pos, buf.length - pos);
      if (len < 0) {
         return Arrays.copyOf(buf, pos);
      }
      pos += len;
   }
}

0

我使用这个。

public static byte[] toByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            byte[] b = new byte[4096];
            int n = 0;
            while ((n = is.read(b)) != -1) {
                output.write(b, 0, n);
            }
            return output.toByteArray();
        } finally {
            output.close();
        }
    }

2
为了帮助 OP 解决当前的问题,可以在答案中添加一些解释说明。 - ρяσѕρєя K

0

这是我的复制粘贴版本:

@SuppressWarnings("empty-statement")
public static byte[] inputStreamToByte(InputStream is) throws IOException {
    if (is == null) {
        return null;
    }
    // Define a size if you have an idea of it.
    ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
    byte[] read = new byte[512]; // Your buffer size.
    for (int i; -1 != (i = is.read(read)); r.write(read, 0, i));
    is.close();
    return r.toByteArray();
}

2
虽然这段代码可能解决了问题,但包括说明真的有助于提高您文章的质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您提供代码建议的原因。 - Ferrybig

0
Java 7 及以后版本:
import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);

22
sun.misc.IOUtils 并不是“Java 7”的一部分。它是一个专有的、实现特定的类,在其他JRE实现中可能不存在,并且在接下来的版本中可能会没有任何警告地消失。 - Holger

0

这对我有效,

if(inputStream != null){
                ByteArrayOutputStream contentStream = readSourceContent(inputStream);
                String stringContent = contentStream.toString();
                byte[] byteArr = encodeString(stringContent);
            }

readSourceContent()

public static ByteArrayOutputStream readSourceContent(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int nextChar;
        try {
            while ((nextChar = inputStream.read()) != -1) {
                outputStream.write(nextChar);
            }
            outputStream.flush();
        } catch (IOException e) {
            throw new IOException("Exception occurred while reading content", e);
        }

        return outputStream;
    }

encodeString()


public static byte[] encodeString(String content) throws UnsupportedEncodingException {
        byte[] bytes;
        try {
            bytes = content.getBytes();

        } catch (UnsupportedEncodingException e) {
            String msg = ENCODING + " is unsupported encoding type";
            log.error(msg,e);
            throw new UnsupportedEncodingException(msg, e);
        }
        return bytes;
    }

为什么要先转换为String,然后再转换为byte[](这可能会影响二进制数据)? ByteArrayOutputStream.toByteArray()方法:https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html#toByteArray() - Thomas Perl

0

你可以使用Cactoos(我是其中的开发者之一):

import org.cactoos.bytes.BytesOf;
byte[] array = new BytesOf(stream).asBytes();

你也可以将流转换为 String

import org.cactoos.text.TextOf;
String txt = new TextOf(stream).asString();

asBytes()asString()方法都会抛出受检查的Exception。如果你不想捕获它,可以使用Unchecked*修饰符,例如:

import org.cactoos.bytes.BytesOf;
import org.cactoos.bytes.UncheckedBytes;
byte[] array = new UncheckedBytes(new BytesOf(stream)).asBytes();

0

你可以尝试 Cactoos

byte[] array = new BytesOf(stream).bytes();

0

另一种情况是通过流获取正确的字节数组,在向服务器发送请求并等待响应后。

/**
         * Begin setup TCP connection to PC app
         * to open integrate connection between mobile app and pc app (or mobile app)
         */
        mSocket = new Socket(IP, port);
       // mSocket.setSoTimeout(30000);

        DataOutputStream mDos = new DataOutputStream(mSocket.getOutputStream());

        String str = "MobileRequest#" + params[0] + "#<EOF>";

        mDos.write(str.getBytes());

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /* Since data are accepted as byte, all of them will be collected in the
        following byte array which initialised with accepted data length. */
        DataInputStream mDis = new DataInputStream(mSocket.getInputStream());
        byte[] data = new byte[mDis.available()];

        // Collecting data into byte array
        for (int i = 0; i < data.length; i++)
            data[i] = mDis.readByte();

        // Converting collected data in byte array into String.
        String RESPONSE = new String(data);

0
如果您使用ByteArrayOutputStream,那么您将进行额外的复制。如果您在开始读取流之前知道流的长度(例如InputStream实际上是FileInputStream,并且您可以在文件上调用file.length(),或者InputStream是zipfile条目InputStream,并且您可以调用zipEntry.length()),那么最好直接写入byte[]数组--它使用一半的内存并节省时间。
// Read the file contents into a byte[] array
byte[] buf = new byte[inputStreamLength];
int bytesRead = Math.max(0, inputStream.read(buf));

// If needed: for safety, truncate the array if the file may somehow get
// truncated during the read operation
byte[] contents = bytesRead == inputStreamLength ? buf
                  : Arrays.copyOf(buf, bytesRead);

注意:上面的最后一行涉及到在读取流时文件被截断的情况,如果您需要处理这种可能性,但如果文件在读取流时变得更长,则byte[]数组中的内容将不会被延长以包括新的文件内容,该数组将仅被截断为旧长度。


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