如何将整个输入流读到字节数组?
当前回答
在将S3对象转换为ByteArray时,我们看到一些AWS事务的延迟。
注意:S3对象为PDF文档(最大大小为3mb)。
我们使用选项#1将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
其他回答
您可以使用cactoos库提供可重用的面向对象的Java组件。 这个库强调OOP,因此没有静态方法、null等等,只有真实对象及其契约(接口)。 像读取InputStream这样的简单操作可以这样执行
final InputStream input = ...;
final Bytes bytes = new BytesOf(input);
final byte[] array = bytes.asBytes();
Assert.assertArrayEquals(
array,
new byte[]{65, 66, 67}
);
使用专用类型Bytes来处理数据结构byte[]使我们能够使用OOP策略来解决手头的任务。 一些程序性的“效用”方法将禁止我们做的事情。 例如,您需要将从此InputStream读取的字节封装到Base64。 在本例中,您将使用Decorator模式并在Base64的实现中封装Bytes对象。 Cactoos已经提供了这样的实现:
final Bytes encoded = new BytesBase64(
new BytesOf(
new InputStreamOf("XYZ")
)
);
Assert.assertEquals(new TextOf(encoded).asString(), "WFla");
您可以使用Decorator模式以同样的方式解码它们
final Bytes decoded = new Base64Bytes(
new BytesBase64(
new BytesOf(
new InputStreamOf("XYZ")
)
)
);
Assert.assertEquals(new TextOf(decoded).asString(), "XYZ");
无论你的任务是什么,你都可以创建自己的Bytes实现来解决它。
您可以使用Apache Commons IO来处理这个任务和类似的任务。
IOUtils类型有一个静态方法来读取InputStream并返回一个字节[]。
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
这将在内部创建一个ByteArrayOutputStream并将字节复制到输出,然后调用toByteArray()。它通过以4KiB为块复制字节来处理大文件。
如果你使用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。
您需要从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();
这是我的复制粘贴版本:
@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();
}
推荐文章
- 如何使一个Java通用方法静态?
- for-each循环和迭代器,哪个更有效?
- 泛型类中的静态方法?
- 如何在JPA中持久化类型列表<字符串>的属性?
- 考虑在配置中定义一个'package'类型的bean [Spring-Boot]
- Java注释中的/**和/*
- java8 LocalDate Jackson格式
- Android Studio谷歌JAR文件导致GC开销限制超过错误
- 如何在Intellij生成串行版本UID
- “比较法违反其总合同!”
- 从Java项目生成UML类图
- 正确地从一个<Integer>的列表中移除一个整数
- Java开关语句:需要常量表达式,但它是常量
- Java的assertEquals方法可靠吗?
- 如何在Java中获得系统变量值?