首页 文章

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

提问于
浏览
724

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

30 回答

  • 6

    Java 7及更高版本:

    import sun.misc.IOUtils;
    ...
    InputStream in = ...;
    byte[] buf = IOUtils.readFully(in, -1, false);
    
  • 2

    请参阅 InputStream.available() 文档:

    特别重要的是要意识到,不得使用此方法来调整容器大小,并假设您可以读取整个流而无需调整容器大小 . 这些调用者应该将他们读取的所有内容写入ByteArrayOutputStream并将其转换为字节数组 . 或者,如果您正在从文件中读取,File.length将返回文件的当前长度(虽然假设文件的长度无法更改可能不正确,但读取文件本质上是有趣的) .

  • 9

    你可以试试Cactoos

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

    下面的代码

    public static byte[] serializeObj(Object obj) throws IOException {
      ByteArrayOutputStream baOStream = new ByteArrayOutputStream();
      ObjectOutputStream objOStream = new ObjectOutputStream(baOStream);
    
      objOStream.writeObject(obj); 
      objOStream.flush();
      objOStream.close();
      return baOStream.toByteArray(); 
    }
    

    要么

    BufferedImage img = ...
    ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
    ImageIO.write(img, "jpeg", baos);
    baos.flush();
    byte[] result = baos.toByteArray();
    baos.close();
    
  • -1

    如果有人仍在寻找没有依赖关系的解决方案,并且 If you have a file .

    1)DataInputStream

    byte[] data = new byte[(int) file.length()];
     DataInputStream dis = new DataInputStream(new FileInputStream(file));
     dis.readFully(data);
     dis.close();
    

    2)ByteArrayOutputStream

    InputStream is = new FileInputStream(file);
     ByteArrayOutputStream buffer = new ByteArrayOutputStream();
     int nRead;
     byte[] data = new byte[(int) file.length()];
     while ((nRead = is.read(data, 0, data.length)) != -1) {
         buffer.write(data, 0, nRead);
     }
    

    3)RandomAccessFile

    RandomAccessFile raf = new RandomAccessFile(file, "r");
     byte[] data = new byte[(int) raf.length()];
     raf.readFully(data);
    
  • 14

    这是我的复制粘贴版本:

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

    我试图用编写垃圾数据的修复来编辑@ numan的答案,但编辑被拒绝了 . 虽然这段简短的代码没什么了不起的,但我看不到任何其他更好的答案 . 这是对我最有意义的:

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024]; // you can configure the buffer size
    int length;
    
    while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length); //copy streams
    in.close(); // call this in a finally block
    
    byte[] result = out.toByteArray();
    

    btw不需要关闭ByteArrayOutputStream . 为了便于阅读,省略了try / finally结构

  • 34

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

    /**
             * 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);
    
  • 107

    如果您碰巧使用google guava,它将如下所示:

    byte[] bytes = ByteStreams.toByteArray(inputStream);
    
  • 1

    你真的需要这个图像作为 byte[] 吗?您对 byte[] 的期望是什么 - 图像文件的完整内容,以图像文件所处的格式编码,还是RGB像素值?

    此处的其他答案将向您展示如何将文件读入 byte[] . 您的 byte[] 将包含文件的确切内容,您需要对其进行解码才能对图像数据执行任何操作 .

    Java用于读取(和写入)图像的标准API是ImageIO API,您可以在包 javax.imageio 中找到它 . 您只需一行代码即可从文件中读取图像:

    BufferedImage image = ImageIO.read(new File("image.jpg"));
    

    这将给你 BufferedImage ,而不是 byte[] . 要获取图像数据,可以在 BufferedImage 上调用 getRaster() . 这将为您提供一个 Raster 对象,它具有访问像素数据的方法(它有几个 getPixel() / getPixels() 方法) .

    查找 javax.imageio.ImageIOjava.awt.image.BufferedImagejava.awt.image.Raster 等的API文档 .

    默认情况下,ImageIO支持多种图像格式:JPEG,PNG,BMP,WBMP和GIF . 可以添加对更多格式的支持(您需要一个实现ImageIO服务提供程序接口的插件) .

    另请参阅以下教程:Working with Images

  • 0
    Input Stream is ...
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    int next = in.read();
    while (next > -1) {
        bos.write(next);
        next = in.read();
    }
    bos.flush();
    byte[] result = bos.toByteArray();
    bos.close();
    
  • 110
    public static byte[] getBytesFromInputStream(InputStream is) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream(); 
        byte[] buffer = new byte[0xFFFF];
        for (int len = is.read(buffer); len != -1; len = is.read(buffer)) { 
            os.write(buffer, 0, len);
        }
        return os.toByteArray();
    }
    
  • 1

    使用vanilla Java的 DataInputStream 及其 readFully 方法(至少从Java 1.4开始存在):

    ...
    byte[] bytes = new byte[(int) file.length()];
    DataInputStream dis = new DataInputStream(new FileInputStream(file));
    dis.readFully(bytes);
    ...
    

    这种方法还有其他一些风格,但我一直都在使用这个用例 .

  • 0

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

    Note 此解决方案擦除 carriage return ('\r')并且可能不合适 .

  • 8
    /*InputStream class_InputStream = null;
    I am reading class from DB 
    class_InputStream = rs.getBinaryStream(1);
    Your Input stream could be from any source
    */
    int thisLine;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    while ((thisLine = class_InputStream.read()) != -1) {
        bos.write(thisLine);
    }
    bos.flush();
    byte [] yourBytes = bos.toByteArray();
    
    /*Don't forget in the finally block to close ByteArrayOutputStream & InputStream
     In my case the IS is from resultset so just closing the rs will do it*/
    
    if (bos != null){
        bos.close();
    }
    
  • 213

    @Adamski:你可以完全避免缓冲 .

    http://www.exampledepot.com/egs/java.io/File2ByteArray.html复制的代码(是的,它非常详细,但需要的内存大小是另一种解决方案的一半 . )

    // Returns the contents of the file in a byte array.
    public static byte[] getBytesFromFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);
    
        // Get the size of the file
        long length = file.length();
    
        // You cannot create an array using a long type.
        // It needs to be an int type.
        // Before converting to an int type, check
        // to ensure that file is not larger than Integer.MAX_VALUE.
        if (length > Integer.MAX_VALUE) {
            // File is too large
        }
    
        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];
    
        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }
    
        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }
    
        // Close the input stream and return bytes
        is.close();
        return bytes;
    }
    
  • 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 []数组中的内容将不会延长到包含新文件内容,该数组将简单地截断为旧的inputStreamLength .

  • 0

    您可以使用Apache Commons IO来处理此类和类似的任务 .

    IOUtils 类型有一个静态方法来读取 InputStream 并返回 byte[] .

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

    在内部创建 ByteArrayOutputStream 并将字节复制到输出,然后调用 toByteArray() . 它通过复制4KiB块中的字节来处理大文件 .

  • 11

    和往常一样,Spring framework(自3.2.2以来的spring-core)也有适合你的东西: StreamUtils.copyToByteArray()

  • 3

    Safe solution (正确具有 close 流的功能):

    • Java 9版本:
    final byte[] bytes;
    try (inputStream) {
        bytes = inputStream.readAllBytes();
    }
    
    • Java 8版本:
    public static byte[] readAllBytes(InputStream inputStream) throws IOException {
        final int bufLen = 4 * 0x400; // 4KB
        byte[] buf = new byte[bufLen];
        int readLen;
        IOException exception = null;
    
        try {
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
                    outputStream.write(buf, 0, readLen);
    
                return outputStream.toByteArray();
            }
        } catch (IOException e) {
            exception = e;
            throw e;
        } finally {
            if (exception == null) inputStream.close();
            else try {
                inputStream.close();
            } catch (IOException e) {
                exception.addSuppressed(e);
            }
        }
    }
    
    • Kotlin版本(与Java v . <9兼容):
    @Throws(IOException::class)
    fun InputStream.readAllBytes(): ByteArray {
        val bufLen = 4 * 0x400 // 4KB
        val buf = ByteArray(bufLen)
        var readLen: Int = 0
    
        ByteArrayOutputStream().use { o ->
            this.use { i ->
                while (i.read(buf, 0, bufLen).also { readLen = it } != -1)
                    o.write(buf, 0, readLen)
            }
    
            return o.toByteArray()
        }
    }
    

    为了避免嵌套 use ,请参阅here .

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

    最后,经过二十年,有一个简单的解决方案,无需第三方库,多亏了Java 9

    InputStream is;
    …
    byte[] array = is.readAllBytes();
    

    另请注意解决重复需求的便捷方法readNBytes(byte[] b, int off, int len)transferTo(OutputStream) .

  • 1

    Java 9将为您提供一个很好的方法:

    InputStream in = ...;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    in.transferTo( bos );
    byte[] bytes = bos.toByteArray();
    
  • 1

    如果您不想使用Apache commons-io库,则此片段取自sun.misc.IOUtils类 . 它几乎是使用ByteBuffers的常见实现的两倍:

    public static byte[] readFully(InputStream is, int length, boolean readAll)
            throws IOException {
        byte[] output = {};
        if (length == -1) length = Integer.MAX_VALUE;
        int pos = 0;
        while (pos < length) {
            int bytesToRead;
            if (pos >= output.length) { // Only expand when there's no room
                bytesToRead = Math.min(length - pos, output.length + 1024);
                if (output.length < pos + bytesToRead) {
                    output = Arrays.copyOf(output, pos + bytesToRead);
                }
            } else {
                bytesToRead = output.length - pos;
            }
            int cc = is.read(output, pos, bytesToRead);
            if (cc < 0) {
                if (readAll && length != Integer.MAX_VALUE) {
                    throw new EOFException("Detect premature EOF");
                } else {
                    if (output.length != pos) {
                        output = Arrays.copyOf(output, pos);
                    }
                    break;
                }
            }
            pos += cc;
        }
        return output;
    }
    
  • 1
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    while (true) {
        int r = in.read(buffer);
        if (r == -1) break;
        out.write(buffer, 0, r);
    }
    
    byte[] ret = out.toByteArray();
    
  • 987

    如果出于某种原因将其包装在DataInputStream中,只需使用read来敲击它,直到它为你提供-1或你要求的整个块 .

    public int readFully(InputStream in, byte[] data) throws IOException {
        int offset = 0;
        int bytesRead;
        boolean read = false;
        while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
            read = true;
            offset += bytesRead;
            if (offset >= data.length) {
                break;
            }
        }
        return (read) ? offset : -1;
    }
    
  • 0

    您需要读取 InputStream 中的每个字节并将其写入 ByteArrayOutputStream . 然后,您可以通过调用 toByteArray() 来检索基础字节数组;例如

    InputStream is = ...
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    
    int nRead;
    byte[] data = new byte[16384];
    
    while ((nRead = is.read(data, 0, data.length)) != -1) {
      buffer.write(data, 0, nRead);
    }
    
    return buffer.toByteArray();
    
  • 406

    我知道现在为时已晚,但我认为更清晰的解决方案更具可读性......

    /**
     * method converts {@link InputStream} Object into byte[] array.
     * 
     * @param stream the {@link InputStream} Object.
     * @return the byte[] array representation of received {@link InputStream} Object.
     * @throws IOException if an error occurs.
     */
    public static byte[] streamToByteArray(InputStream stream) throws IOException {
    
        byte[] buffer = new byte[1024];
        ByteArrayOutputStream os = new ByteArrayOutputStream();
    
        int line = 0;
        // read bytes from stream, and store them in buffer
        while ((line = stream.read(buffer)) != -1) {
            // Writes bytes from byte array (buffer) into output stream.
            os.write(buffer, 0, line);
        }
        stream.close();
        os.flush();
        os.close();
        return os.toByteArray();
    }
    
  • 0

    我们看到一些AWS事务延迟,同时将S3对象转换为ByteArray .

    注意:S3 Object是PDF文档(最大大小为3 mb) .

    我们使用选项#1(org.apache.commons.io.IOUtils)将S3对象转换为ByteArray . 我们注意到S3提供了内置的IOUtils方法来将S3对象转换为ByteArray,我们要求您确认将S3对象转换为ByteArray的最佳方法是什么,以避免延迟 .

    选项1:

    import org.apache.commons.io.IOUtils;
    is = s3object.getObjectContent();
    content =IOUtils.toByteArray(is);
    

    选项#2:

    import com.amazonaws.util.IOUtils;
    is = s3object.getObjectContent();
    content =IOUtils.toByteArray(is);
    

    如果我们有更好的方法将s3对象转换为bytearray,也请告诉我

相关问题