如何将整个输入流读到字节数组?
当前回答
如果您不想使用Apache common -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;
}
其他回答
你真的需要图像作为字节[]吗?你在字节[]中到底期望什么-图像文件的完整内容,以图像文件的任何格式编码,或RGB像素值?
这里的其他答案向您展示了如何将文件读入字节[]。您的字节[]将包含文件的确切内容,并且您需要对其进行解码才能对图像数据进行处理。
用于读取(和写入)图像的Java标准API是ImageIO API,您可以在javax.imageio包中找到它。你可以用一行代码从文件中读入一张图片:
BufferedImage image = ImageIO.read(new File("image.jpg"));
这将给您一个BufferedImage,而不是一个字节[]。要获取图像数据,可以在BufferedImage上调用getRaster()。这将为您提供一个光栅对象,该对象具有访问像素数据的方法(它有几个getPixel() / getPixels()方法)。
查找javax.imageio的API文档。ImageIO java.awt.image。BufferedImage, java。awt。image。raster等等。
ImageIO默认支持多种图像格式:JPEG, PNG, BMP, WBMP和GIF。可以添加对更多格式的支持(您需要一个实现ImageIO服务提供程序接口的插件)。
另请参阅下面的教程:使用图像
下面是一个优化的版本,尽量避免复制数据字节:
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;
}
}
你可以使用Cactoos(我是它的开发者之一):
import org.cactoos.bytes.BytesOf;
byte[] array = new BytesOf(stream).asBytes();
你也可以将流转换为字符串:
import org.cactoos.text.TextOf;
String txt = new TextOf(stream).asString();
asBytes()和asString()方法都会抛出checked Exception。如果你不想捕获它,使用Unchecked*装饰器,例如:
import org.cactoos.bytes.BytesOf;
import org.cactoos.bytes.UncheckedBytes;
byte[] array = new UncheckedBytes(new BytesOf(stream)).asBytes();
使用普通Java的DataInputStream和它的readFully方法(至少从Java 1.4开始存在):
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
这个方法还有其他一些形式,但在这个用例中,我一直使用这个方法。
另一种情况是在发送请求到服务器并等待响应后,通过流获得正确的字节数组。
/**
* 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);
推荐文章
- 我如何修复一个NoSuchMethodError?
- Maven surefire找不到ForkedBooter类
- Java 8:我如何在流中使用异常抛出方法?
- 去下一次迭代在java For循环
- 在Java中使用什么数据类型来表示钱?
- Class.getResource()和ClassLoader.getResource()之间的区别是什么?
- 如何通过传递特定日期来确定星期几?
- 如何将DecimalFormat的小数分隔符从逗号更改为点/点?
- 控制jar工件的Maven最终名称
- Spring-MVC控制器中的404触发器?
- 为什么生成较长的serialVersionUID而不是简单的1L?
- JAX-RS / Jersey如何自定义错误处理?
- 从标准输入中捕获字符,而不需要等待按enter键
- 在执行JpaTest时无法找到@SpringBootConfiguration
- _JAVA_OPTIONS, JAVA_TOOL_OPTIONS和JAVA_OPTS之间的区别