web-dev-qa-db-ja.com

java.net.URLがbyte []に​​ストリームを読み込む

URLから(Java packageJava.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();

私の2番目のアプローチはこれでした(contentlengthが別の方法で取得されているのを見るでしょう):

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

両方のコードが破損したイメージになります...私はすでにこの記事を読んでいます stackoverflowから

41
tim.kaufner

提供されたコンテンツの長さが実際に正しいという保証はありません。次のようなものを試してください。

_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()を呼び出すことでバイト配列を取得できます。

このコードはテストされていません(回答ボックスに書いただけです)が、それは私があなたが望んでいるものにかなり近い近似値です。

58
RTBarnard

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)

27
Adi

クリーンなソリューションは次のとおりです。

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();
}
20
Ron Reiter
byte[] b = IOUtils.toByteArray((new URL( )).openStream()); //idiom

ただし、上記の例ではストリームが閉じられていないことに注意してください。

(共通文字コーデックを使用して)(76文字)チャンクが必要な場合...

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

接続と読み取りタイムアウトの問題に言及している人がいないことに非常に驚いています。 (特に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
    }
}
10
NumberFour

コンテンツの長さは単なるHTTPヘッダーです。信用できない。ストリームからできることをすべて読んでください。

利用可能は間違いなく間違いです。ブロックせずに読み取れるのは、バイト数だけです。

別の問題は、リソースの処理です。いずれにしても、ストリームを閉じる必要があります。 try/catch/finallyがそれを行います。

1
Thomas Jung