IT-Swarm.Net

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

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

750
JGC

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

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

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

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

1019
Rich Seller

您需要读取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();
416
Adamski

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

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

还要注意便利方法 readNBytes(byte[] b, int off, int len)transferTo(OutputStream) 解决重复需求。

230
Holger

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

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

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

113
dermoritz

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

byte[] bytes = ByteStreams.toByteArray(inputStream);
112
bertie
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();
}
37
oliverkn

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

34
Arne Burmeister

你真的需要将图像作为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服务提供程序接口的插件)。

另请参阅以下教程: 使用图像

20
Jesper

如果您不想使用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;
}
14
Kristian Kraljic

如果有人仍在寻找没有依赖关系的解决方案和 如果你有一个文件

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);
12
harsh_v
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();
9
YulCheney

@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;
}
8
pihentagy
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();
8
Aturio

安全解决方案 (正确地具有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 version(与Java≤8兼容):

    @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这里

4
Mir-Ismaili

Java 9最终将为您提供一个Nice方法:

InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
3
Christian Ullenboom

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

/**
 * 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();
}
2
Simple-Solution

Java 7及更高版本:

import Sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
1
Antonio

Java 8方式(感谢 BufferedReader Adam 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')并且可能不合适。

1
Ilya Bystrov

请参阅InputStream.available()文档:

特别重要的是要意识到你不能使用这种方法来确定容器的大小,并假设你可以阅读流的整个而无需调整容器的大小。这些调用者应该将他们读取的所有内容写入ByteArrayOutputStream 并将其转换为字节数组。或者,如果您正在从文件中读取,File.length将返回文件的当前长度(尽管假设文件的长度不能更改可能不正确,[。_____。]阅读文件本身就很有趣。

1
yichouangle

我试图编辑@ 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结构

1
akostadinov

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

注意:S3对象是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,也请告诉我

0
Bharathiraja S

你可以试试 Cactoos

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

将它包装在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
Tatarize

我用这个。

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
cchcc

这是我的复制粘贴版本:

@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();
}
0
Daniel De León

这是一个优化版本,它试图尽可能避免复制数据字节:

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
Christian d'Heureuse

如果使用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
Luke Hutchison