Подтвердить что ты не робот

Java.net.URL чтение потока в байт []

Я пытаюсь прочитать изображение с 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();

Моим вторым подходом был этот (поскольку вы увидите, что длина содержимого выбирается другим способом):

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

Оба кода приводят к поврежденному изображению... Я уже прочитал этот пост qaru.site/info/178263/...

4b9b3361

Ответ 1

Нет гарантии, что длина контента, которую вы предоставили, на самом деле верна. Попробуйте что-то похожее на следующее:

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 appropriate.
}
finally {
  if (is != null) { is.close(); }
}

Затем вы получите данные изображения в baos, из которых вы можете получить массив байтов, вызвав baos.toByteArray().

Этот код не проверен (я просто написал его в поле ответа), но это довольно близкое приближение к тому, что, как я думаю, вам нужно.

Ответ 2

Просто протягивая Барнардсу ответ с помощью commons-io. Отдельный ответ, потому что я не могу форматировать код в комментариях.

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

Ответ 3

Здесь чистое решение:

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

Ответ 4

byte[] b = IOUtils.toByteArray((new URL( )).openStream()); //idiom

Обратите внимание, однако, что поток не закрыт в приведенном выше примере.

если вы хотите (76-символьный) фрагмент (с использованием общедоступного кодека)...

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

Ответ 5

Я очень удивлен, что никто здесь не упомянул проблему соединения и таймаута чтения. Это может произойти (особенно на 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
    }
}

Ответ 6

Длина содержимого - это только HTTP-заголовок. Вы не можете этому доверять. Просто прочитайте все, что вы можете, из потока.

Доступно, безусловно, неправильно. Это просто количество байтов, которые можно читать без блокировки.

Другая проблема - это обработка ваших ресурсов. Закрытие потока должно произойти в любом случае. try/catch/, наконец, сделаем это.