Могу ли я прочитать весь файл с одним чтением в Java на Android? - PullRequest
1 голос
/ 03 декабря 2010

На андроиде при чтении из входного потока, который представляет файл в интернете, если я запрашиваю чтение всей длины файла, есть ли какая-то причина, по которой мой байтовый массив должен заполняться только частично после вызова?

Ответы [ 3 ]

1 голос
/ 03 декабря 2010

Обычная команда чтения считывает некоторое количество байтов до требуемой длины.Программист должен включить проверку возвращаемого значения (которое говорит вам, сколько байтов было прочитано).Существует также метод readFully, который заставляет его читать всю запрошенную длину, но он может блокировать в течение очень долгого времени, предотвращая разрыв в середине чтения большого потока.

1 голос
/ 03 декабря 2010

есть ли причина, по которой мой байтовый массив должен заполняться только частично после вызова?

Да. Чтобы вашему Android-приложению не пришлось ждать загрузки всего потока, прежде чем вернуться из вызова read.

В вашем конкретном случае использования это (очевидно) неприятность. В других случаях использования крайне важно, чтобы read вел себя следующим образом:

  • Приложению может потребоваться начать обработку и доставку результатов пользователю, пока удаленный сервер все еще отправляет данные.

  • Возможно, удаленный сервер действительно ожидает какой-то ответ уровня приложения от клиента, прежде чем отправлять больше данных. (Это не будет применяться, если вы используете HTTP или FTP. Но поток, из которого вы читаете, вероятно, оборачивает поток сокета транспортного уровня, и на этом уровне нет никаких сведений о деталях протокола уровня представления.)

Решение:

  • Используйте цикл и продолжайте чтение, пока read не вернет ноль.
  • Если вы используете Apache HttpClient, есть способы получить все содержимое ответа.
  • Apache Commons включает класс IOUtils, который имеет вспомогательные методы для чтения всего потока или читателя.

Кстати, это поведение четко указано в javadocs для методов read(byte[], ...).

1 голос
/ 03 декабря 2010

Метод read(byte[]) в потоках Java может считывать меньше байтов, чем запрошено.

По файлу в интернете Полагаю, вы имеете в виду содержимое HTTP-URL.

Некоторые ответы HTTP не дают заранее Content-Length, что также не позволяет предварительно выделить массив байтов правильного размера, как вы, похоже, делаете.

Возможно, вам будет интересно узнать, что доступная на Android клиентская библиотека Apache http уже предоставляет вспомогательный метод EntityUtils.toByteArray(), который полностью выбирает содержимое URL-адреса и возвращает его в виде байтового массива правильного размера.

Вот фрагмент кода, использующего его:

public byte[] fetchURL(String url) throws IOException, ClientProtocolException {
      HttpClient httpclient = new DefaultHttpClient();
      HttpGet httpget = new HttpGet(url);
      HttpResponse response = httpclient.execute(httpget);
      HttpEntity entity = response.getEntity();
      return EntityUtils.toByteArray(entity);
}

Обратите внимание, что чтение всего ответа в памяти не всегда является лучшим решением. Может быть предпочтительным сообщить пользователю о ходе загрузки или проанализировать большой документ постепенно. На самом деле ответ может даже не помещаться в ОЗУ (например, большой видеопоток).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...