簡體   English   中英

java.net.URL 讀取流到字節[]

[英]java.net.URL read stream to byte[]

我正在嘗試從 URL(使用 Java 包java.net.URL )讀取圖像到字節 []。 “一切”工作正常,除了內容沒有完全從流中讀取(圖像已損壞,它不包含所有圖像數據)......字節數組被保存在數據庫(BLOB)中. 我真的不知道正確的方法是什么,也許你可以給我一個提示。 :)

這是我的第一種方法(代碼格式化,刪除了不必要的信息......):

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();

我的第二種方法是這個(你會看到contentlength是以另一種方式獲取的):

URL u = new URL(content);
openStream = u.openStream();
int contentLength = openStream.available();
byte[] binaryData = new byte[contentLength];
openStream.read(binaryData);
openStream.close();

這兩個代碼都會導致圖像損壞……我已經從 Stack Overflow閱讀了這篇文章。

無法保證您提供的內容長度實際上是正確的。 嘗試類似於以下內容:

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(); }
}

然后,您將在baos中獲得圖像數據,您可以通過調用baos.toByteArray()從中獲取字節數組。

這段代碼未經測試(我只是在答案框中寫了它),但它與我認為您所追求的相當接近。

只是用 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(); }
}

http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toByteArray(java.io.InputStream)

這是一個干凈的解決方案:

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();
}

我很驚訝這里沒有人提到連接和讀取超時的問題。 請求可能會掛起並永遠等待(尤其是在 Android 和/或一些糟糕的網絡連接上)。

以下代碼(也使用 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
    }
}
byte[] b = IOUtils.toByteArray((new URL( )).openStream()); //idiom

但是請注意,在上面的示例中該流並未關閉。

如果你想要一個(76 個字符)塊(使用公共編解碼器)......

byte[] b = Base64.encodeBase64(IOUtils.toByteArray((new URL( )).openStream()), true);

使用 commons-io IOUtils.toByteArray(URL)

String url = "http://localhost:8080/images/anImage.jpg";
byte[] fileContent = IOUtils.toByteArray(new URL(url));

Maven 依賴:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

內容長度只是一個 HTTP 標頭。 你不能相信它。 只需從流中讀取所有內容即可。

可用肯定是錯誤的。 它只是可以在不阻塞的情況下讀取的字節數。

另一個問題是您的資源處理。 在任何情況下都必須關閉流。 try/catch/finally 會做到這一點。

指定超時很重要,尤其是當服務器需要響應時。 使用純 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();
    }
}

使用依賴項,例如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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM