将 URL 中的二进制图像数据读入 HttpUrlConnect::URL 中的 ByteArrayInputStream
Read the binary image data from a URL into a ByteArrayInputStream from HttpUrlConnect::URL
我正在尝试从 URL 中提取图像并将其直接读入 ByteArrayInputStream。我找到了一种方法,但它需要一种图像类型,并且会有各种图像类型,所以我想找到一种简单的方法来直接读取二进制数据。
这是我最近的尝试。我正在使用 BufferedImage,我认为没有必要。
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
//Read in the image
BufferedImage image = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
is = new ByteArrayInputStream(baos.toByteArray());
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
url.openStream().transferTo(baos);
ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray());
transferTo()
方法从 Java 9 开始就存在。如果您应该使用旧版本的 Java,请参阅 here 的替代方法。这个解决方案的主要缺点是它必须先将整个文件读入内存。如果您无论如何都计划将二进制数据转发到其他进程,您可以省略 ByteArray 流并将内容直接传输到 OutputStream。
作为@rmunge 提出的解决方案的替代方案,Apache Commons IO 库提供了 class IOUtils
,这在您的用例中非常有用。
例如,如果您使用的是 Maven,则可以在 pom.xml
中导入包括以下 dependency 的库:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
然后,你可以这样使用IOUtils
:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (
InputStream imageInputStream = url.openStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream()
) {
// You can obtain a byte[] as well if required
// Please, consider write to the actual final OutputStream instead
// of into the intermediate byte array output stream to optimize memory
// consumption
IOUtils.copy(imageInputStream, bOut);
// Create an input stream from the read bytes
ByteArrayInputStream in = new ByteArrayInputStream(bOut.toByteArray());
// ...
} catch (IOException ioe) {
ioe.printStackTrace();
}
或简单地采用这种方法:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
byte[] imageBytes = IOUtils.toByteArray(url);
ByteArrayInputStream in = new ByteArrayInputStream(imageBytes);
对于您的评论,如果问题是您试图避免网络延迟问题,如果 ByteArrayInputStream
的要求不是绝对必要的,正如您在 javadocs 中看到的那样,也许以下代码也可能有帮助:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (InputStream imageInputStream = url.openStream()) {
InputStream in = IOUtils.toBufferedInputStream(imageInputStream);
//...
}
当然,您始终可以使用标准 Java InputStream
和 OutputStream
机制“手动”执行读写:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (
InputStream inputStream = url.openStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, bytesRead);
}
bufferedOutputStream.flush();
// Create an input stream from the read bytes
ByteArrayInputStream in = new ByteArrayInputStream(outputStream.toByteArray());
// ...
} catch (IOException ioe) {
ioe.printStackTrace();
}
如果您需要对底层 URL 连接进行更多控制,您可以使用 URLConnection
or HttpURLConnection
, or many HTTP client libraries like Apache HttpClient or OkHttp 来命名其中的一些连接。
以@LuisCarlos在他的评论中指出的问题为例,为了避免可能的泄漏连接:
URLConnection urlConn = null;
try {
urlConn = url.openConnection();
urlConn.setConnectTimeout(5000);
urlConn.setReadTimeout(30000);
InputStream inputStream = urlConn.getInputStream();
// the rest of the code...
} catch (Exception e) {
}
如果您需要检测实际图像类型,请考虑使用 Tika or JMimeMagic。
这是我发现有效的解决方案。感谢您提供上述两种方法。我宁愿避免外部库,但因为环境真的很痛苦。类似的,我应该可以访问 Java 9 和 transferTo(),但那不起作用。
这位回答者也很有帮助:Convert InputStream(Image) to ByteArrayInputStream
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
InputStream source = url.openStream();
byte[] buf = new byte[8192];
int bytesRead = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((bytesRead = source.read(buf)) != -1) {
baos.write(buf, 0, bytesRead);
}
is = new ByteArrayInputStream(baos.toByteArray());
我正在尝试从 URL 中提取图像并将其直接读入 ByteArrayInputStream。我找到了一种方法,但它需要一种图像类型,并且会有各种图像类型,所以我想找到一种简单的方法来直接读取二进制数据。
这是我最近的尝试。我正在使用 BufferedImage,我认为没有必要。
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
//Read in the image
BufferedImage image = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
is = new ByteArrayInputStream(baos.toByteArray());
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
url.openStream().transferTo(baos);
ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray());
transferTo()
方法从 Java 9 开始就存在。如果您应该使用旧版本的 Java,请参阅 here 的替代方法。这个解决方案的主要缺点是它必须先将整个文件读入内存。如果您无论如何都计划将二进制数据转发到其他进程,您可以省略 ByteArray 流并将内容直接传输到 OutputStream。
作为@rmunge 提出的解决方案的替代方案,Apache Commons IO 库提供了 class IOUtils
,这在您的用例中非常有用。
例如,如果您使用的是 Maven,则可以在 pom.xml
中导入包括以下 dependency 的库:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
然后,你可以这样使用IOUtils
:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (
InputStream imageInputStream = url.openStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream()
) {
// You can obtain a byte[] as well if required
// Please, consider write to the actual final OutputStream instead
// of into the intermediate byte array output stream to optimize memory
// consumption
IOUtils.copy(imageInputStream, bOut);
// Create an input stream from the read bytes
ByteArrayInputStream in = new ByteArrayInputStream(bOut.toByteArray());
// ...
} catch (IOException ioe) {
ioe.printStackTrace();
}
或简单地采用这种方法:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
byte[] imageBytes = IOUtils.toByteArray(url);
ByteArrayInputStream in = new ByteArrayInputStream(imageBytes);
对于您的评论,如果问题是您试图避免网络延迟问题,如果 ByteArrayInputStream
的要求不是绝对必要的,正如您在 javadocs 中看到的那样,也许以下代码也可能有帮助:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (InputStream imageInputStream = url.openStream()) {
InputStream in = IOUtils.toBufferedInputStream(imageInputStream);
//...
}
当然,您始终可以使用标准 Java InputStream
和 OutputStream
机制“手动”执行读写:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (
InputStream inputStream = url.openStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, bytesRead);
}
bufferedOutputStream.flush();
// Create an input stream from the read bytes
ByteArrayInputStream in = new ByteArrayInputStream(outputStream.toByteArray());
// ...
} catch (IOException ioe) {
ioe.printStackTrace();
}
如果您需要对底层 URL 连接进行更多控制,您可以使用 URLConnection
or HttpURLConnection
, or many HTTP client libraries like Apache HttpClient or OkHttp 来命名其中的一些连接。
以@LuisCarlos在他的评论中指出的问题为例,为了避免可能的泄漏连接:
URLConnection urlConn = null;
try {
urlConn = url.openConnection();
urlConn.setConnectTimeout(5000);
urlConn.setReadTimeout(30000);
InputStream inputStream = urlConn.getInputStream();
// the rest of the code...
} catch (Exception e) {
}
如果您需要检测实际图像类型,请考虑使用 Tika or JMimeMagic。
这是我发现有效的解决方案。感谢您提供上述两种方法。我宁愿避免外部库,但因为环境真的很痛苦。类似的,我应该可以访问 Java 9 和 transferTo(),但那不起作用。
这位回答者也很有帮助:Convert InputStream(Image) to ByteArrayInputStream
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
InputStream source = url.openStream();
byte[] buf = new byte[8192];
int bytesRead = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((bytesRead = source.read(buf)) != -1) {
baos.write(buf, 0, bytesRead);
}
is = new ByteArrayInputStream(baos.toByteArray());