java.net.URL 读取流到字节[]
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2295221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.net.URL read stream to byte[]
提问by tim.kaufner
I`m trying to read an image from an URL (with the java package java.net.URL) to a byte[]. "Everything" works fine, except that the content isnt being enterely read from the stream (the image is corrupt, it doesnt contain all the image data)... The byte array is being persisted in a database (BLOB). I really dont know what the correct approach is, maybe you can give me a tip :)
我正在尝试从 URL(使用 java 包java.net.URL)读取图像 到字节 []。“一切”工作正常,除了内容不是从流中读取(图像已损坏,它不包含所有图像数据)......字节数组被持久保存在数据库(BLOB)中。我真的不知道正确的方法是什么,也许你可以给我一个提示:)
This is my first approach (code formatted, removed unnecessary informations...):
这是我的第一种方法(代码格式化,删除了不必要的信息......):
URL u = new URL("http://localhost:8080/images/anImage.jpg");
int contentLength = u.openConnection().getContentLength();
Inputstream openStream = u.openStream();
byte[] binaryData = new byte[contentLength];
openStream.read(binaryData);
openStream.close();
My second approach was this one (as you'll see the contentlength is being fetched another way):
我的第二种方法是这个(你会看到 contentlength 是以另一种方式获取的):
URL u = new URL(content);
openStream = u.openStream();
int contentLength = openStream.available();
byte[] binaryData = new byte[contentLength];
openStream.read(binaryData);
openStream.close();
Both of the code result in a corrupted image... I already read this post from stackoverflow
这两个代码都导致图像损坏......我已经从stackoverflow阅读了这篇文章
采纳答案by RTBarnard
There's no guarantee that the content length you're provided is actually correct. Try something akin to the following:
无法保证您提供的内容长度实际上是正确的。尝试类似于以下内容:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
baos.write(byteChunk, 0, n);
}
}
catch (IOException e) {
System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
e.printStackTrace ();
// Perform any other exception handling that's appropriate.
}
finally {
if (is != null) { is.close(); }
}
You'll then have the image data in baos
, from which you can get a byte array by calling baos.toByteArray()
.
然后您将拥有图像数据baos
,您可以通过调用从中获取字节数组baos.toByteArray()
。
This code is untested (I just wrote it in the answer box), but it's a reasonably close approximation to what I think you're after.
这段代码未经测试(我只是在答案框中写了它),但它与我认为您所追求的相当接近。
回答by Thomas Jung
The content length is just a HTTP header. You cannot trust it. Just read everything you can from the stream.
内容长度只是一个 HTTP 标头。你不能相信它。只需从流中读取所有内容即可。
Available is definitely wrong. It's just the number of bytes that can be read without blocking.
可用肯定是错误的。它只是可以在不阻塞的情况下读取的字节数。
Another issue is your resource handling. Closing the stream has to happen in any case. try/catch/finally will do that.
另一个问题是您的资源处理。在任何情况下都必须关闭流。try/catch/finally 会做到这一点。
回答by Adisesha
Just extending Barnards's answer with commons-io. Separate answer because I can not format code in comments.
只是用 commons-io 扩展 Barnards 的答案。单独的答案,因为我无法在注释中格式化代码。
InputStream is = null;
try {
is = url.openStream ();
byte[] imageBytes = IOUtils.toByteArray(is);
}
catch (IOException e) {
System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
e.printStackTrace ();
// Perform any other exception handling that's appropriate.
}
finally {
if (is != null) { is.close(); }
}
回答by jeff
byte[] b = IOUtils.toByteArray((new URL( )).openStream()); //idiom
Note however, that stream is not closed in the above example.
但是请注意,在上面的示例中该流并未关闭。
if you want a (76-character) chunk (using commons codec)...
如果你想要一个(76 个字符)块(使用公共编解码器)......
byte[] b = Base64.encodeBase64(IOUtils.toByteArray((new URL( )).openStream()), true);
回答by Ron Reiter
Here's a clean solution:
这是一个干净的解决方案:
private byte[] downloadUrl(URL toDownload) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
byte[] chunk = new byte[4096];
int bytesRead;
InputStream stream = toDownload.openStream();
while ((bytesRead = stream.read(chunk)) > 0) {
outputStream.write(chunk, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
return outputStream.toByteArray();
}
回答by NumberFour
I am very surprised that nobody here has mentioned the problem of connection and read timeout. It could happen (especially on Android and/or with some crappy network connectivity) that the request will hang and wait forever.
我很惊讶这里没有人提到连接和读取超时的问题。请求可能会挂起并永远等待(尤其是在 Android 和/或某些糟糕的网络连接上)。
The following code (which also uses Apache IO Commons) takes this into account, and waits max. 5 seconds until it fails:
以下代码(也使用 Apache IO Commons)考虑到了这一点,并等待最大。5 秒,直到它失败:
public static byte[] downloadFile(URL url)
{
try {
URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.connect();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(conn.getInputStream(), baos);
return baos.toByteArray();
}
catch (IOException e)
{
// Log error and return null, some default or throw a runtime exception
}
}
回答by Paul Vargas
It's important to specify timeouts, especially when the server takes to respond. With pure Java, without using any dependency:
指定超时很重要,尤其是当服务器需要响应时。使用纯 Java,不使用任何依赖:
public static byte[] copyURLToByteArray(final String urlStr,
final int connectionTimeout, final int readTimeout)
throws IOException {
final URL url = new URL(urlStr);
final URLConnection connection = url.openConnection();
connection.setConnectTimeout(connectionTimeout);
connection.setReadTimeout(readTimeout);
try (InputStream input = connection.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
final byte[] buffer = new byte[8192];
for (int count; (count = input.read(buffer)) > 0;) {
output.write(buffer, 0, count);
}
return output.toByteArray();
}
}
Using dependencies, e.g., HC Fluent:
使用依赖项,例如HC Fluent:
public byte[] copyURLToByteArray(final String urlStr,
final int connectionTimeout, final int readTimeout)
throws IOException {
return Request.Get(urlStr)
.connectTimeout(connectionTimeout)
.socketTimeout(readTimeout)
.execute()
.returnContent()
.asBytes();
}
回答by alaster
Use commons-io IOUtils.toByteArray(URL):
使用 commons-io IOUtils.toByteArray(URL):
String url = "http://localhost:8080/images/anImage.jpg";
byte[] fileContent = IOUtils.toByteArray(new URL(url));
Maven dependency:
Maven 依赖:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>