Java прочитать файл по url

Обновлено: 05.07.2024

ОТВЕТЫ

Ответ 1

Использование transferFrom() потенциально намного более эффективно, чем простой цикл, который читает из исходного канала и записывает в этот канал. Многие операционные системы могут передавать байты непосредственно из исходного канала в кеш файловой системы, фактически не копируя их.

Проверьте больше об этом здесь.

Примечание. Третий параметр в TransferFrom - это максимальное количество байтов для передачи. Integer.MAX_VALUE будет передавать не более 2 ^ 31 байта, Long.MAX_VALUE не более 2 ^ 63 байта (больше, чем любой существующий файл).

Ответ 2

Используйте apache commons-io, только один код строки:

Ответ 3

Упрощение использования nio:

Ответ 4

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

Ответ 5

Загрузка файла требует, чтобы вы его прочитали, в любом случае вам придется каким-то образом пройти через файл. Вместо строки за строкой вы можете просто прочитать ее байтами из потока:

Ответ 6

Это старый вопрос, но вот краткое, удобочитаемое решение только для JDK с правильно закрытыми ресурсами:

Две строки кода и никаких зависимостей.

Ответ 7

При использовании Java 7+ используйте следующий метод, чтобы загрузить файл из Интернета и сохранить его в каком-либо каталоге:

Ответ 8

Этот ответ почти точно подобен выбранному ответу, но с двумя улучшениями: это метод и он закрывает объект FileOutputStream:

Ответ 9

Ответ 10

Ответ 11

Это еще один вариант java7, основанный на ответе Брайана Риск с использованием инструкции try-with:

Ответ 12

Здесь метод, который не генерирует исключения для сетевых ошибок (только для действительно исключительных проблем, таких как неверный URL-адрес или проблемы с записью в файл)

Ответ 13

Существует проблема с простым использованием:

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

Ответ 14

В отличие от одной строки кода:

этот код даст вам больше контроля над процессом и позволит указать не только тайм-ауты, но User-Agent и Referer значения, которые имеют решающее значение для многих веб-сайтов.

Ответ 15

В библиотеке underscore-java есть метод U.fetch(url).

Ответ 16

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

(Помечается как wiki сообщества, не стесняйтесь добавлять информацию или исправления)

Ответ 17

Ответ 18

Вы можете сделать это в 1 строке, используя netloader для Java:

Ответ 19

Если вы находитесь за прокси-сервером, вы можете установить прокси-серверы в java-программе, как показано ниже:

Если вы не находитесь за прокси-сервером, не включайте строки в свой код. Полный рабочий код для загрузки файла, когда вы находитесь за прокси.

Ответ 20

Ниже приведен пример кода для загрузки фильма из Интернета с использованием кода Java:

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

Наконец, мы поговорим о том, как возобновить загрузку в случае сбоя подключения до того, как будет прочитан весь файл.

2. Использование Java IO

Самый простой API, который мы можем использовать для загрузки файла, - это Java IO. Мы можем использовать класс URL, чтобы открыть соединение с файлом, который мы хотим загрузить. Чтобы эффективно прочитать файл, мы будем использовать метод openStream () для получения InputStream:

При чтении из InputStream рекомендуется обернуть его в BufferedInputStream, чтобы повысить производительность.

Увеличение производительности происходит за счет буферизации. При чтении по одному байту с использованием метода read () каждый вызов метода подразумевает системный вызов базовой файловой системы. Когда JVM вызывает системный вызов read () , контекст выполнения программы переключается из пользовательского режима в режим ядра и обратно.

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

Для записи байтов, прочитанных из URL-адреса, в наш локальный файл мы будем использовать метод write () из класса FileOutputStream :

При использовании BufferedInputStream метод read () будет читать столько байтов, сколько мы установили для размера буфера. В нашем примере мы уже делаем это, читая блоки по 1024 байта за раз, поэтому BufferedInputStream не нужен.

Приведенный выше пример очень подробный, но, к счастью, начиная с Java 7 у нас есть класс Files, который содержит вспомогательные методы для обработки операций ввода-вывода. Мы можем использовать метод Files.copy () для чтения всех байтов из InputStream и копирования их в локальный файл:

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

К счастью, Java предлагает нам пакет NIO, в котором есть методы для передачи байтов напрямую между 2 каналами без буферизации.

Подробности мы рассмотрим в следующем разделе.

3. Использование NIO

Пакет Java NIO предлагает возможность передавать байты между 2 каналами без их буферизации в памяти приложения.

Чтобы прочитать файл по нашему URL, мы создадим новый ReadableByteChannel из потока URL :

Байты, считанные из ReadableByteChannel, будут переданы в FileChannel, соответствующий файлу, который будет загружен:

Мы будем использовать метод transferFrom () из класса ReadableByteChannel для загрузки байтов с заданного URL-адреса в наш FileChannel :

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

В системах Linux и UNIX эти методы используют технику нулевого копирования , которая уменьшает количество переключений контекста между режимом ядра и пользовательским режимом.

4. Использование библиотек

В приведенных выше примерах мы видели, как можно загружать контент с URL-адреса, просто используя основные функции Java. Мы также можем использовать функциональность существующих библиотек, чтобы упростить нашу работу, когда настройки производительности не нужны.

Например, в реальном сценарии нам нужно, чтобы код загрузки был асинхронным.

Мы могли бы обернуть всю логику в Callable или использовать для этого существующую библиотеку.

Загруженный контент будет помещен в FileOutputStream :

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

4.2. Apache Commons IO

Еще одна широко используемая библиотека для операций ввода-вывода - Apache Commons IO. Из документации Javadoc видно, что существует служебный класс с именем FileUtils, который используется для общих задач работы с файлами.

Чтобы загрузить файл по URL-адресу, мы можем использовать этот однострочный файл:

С точки зрения производительности этот код такой же, как и тот, который мы продемонстрировали в разделе 2.

Базовый код использует те же концепции чтения в цикле нескольких байтов из InputStream и записи их в OutputStream .

Одно из отличий заключается в том, что здесь класс URLConnection используется для управления тайм-аутом соединения, чтобы загрузка не блокировалась на большое количество времени:

5. Возобновляемая загрузка

Учитывая, что интернет-соединение время от времени прерывается, для нас полезно иметь возможность возобновить загрузку вместо того, чтобы загружать файл снова с нулевого байта.

Давайте перепишем первый пример из предыдущего, чтобы добавить эту функциональность.

Теперь, когда у нас есть общий размер содержимого файла, мы можем проверить, частично ли загружен наш файл. Если это так, мы возобновим загрузку с последнего байта, записанного на диск:

What happens here is that we've configured the URLConnection to request the file bytes in a specific range. The range will start from the last downloaded byte and will end at the byte corresponding to the size of the remote file.

Another common way to use the Range header is for downloading a file in chunks by setting different byte ranges. For example, to download 2 KB file, we can use the range 0 – 1024 and 1024 – 2048.

Another subtle difference from the code at section 2. is that the FileOutputStream is opened with the append parameter set to true:

After we've made this change the rest of the code is identical to the one we've seen in section 2.

6. Conclusion

В этой статье мы увидели несколько способов загрузки файла по URL-адресу в Java.

Наиболее распространенная реализация - это та, в которой мы буферизуем байты при выполнении операций чтения / записи. Эта реализация безопасна для использования даже для больших файлов, потому что мы не загружаем весь файл в память.

Мы также увидели, как можно реализовать загрузку с нулевым копированием с помощью каналов Java NIO . Это полезно, потому что оно минимизировало количество переключений контекста, выполняемых при чтении и записи байтов, а при использовании прямых буферов байты не загружаются в память приложения.

Работу с потоками ввода-вывода мы уже изучили, работу с файлами изучили, что же изучить дальше? А как насчет работы с сетью и интернетом? Звучит многообещающе, не так ли?

В Java работать с интернетом не сложнее, чем работать с файлами. Ну разве что совсем чуть-чуть.

Для работы с ресурсами в интернете в Java есть специальный класс — URL . Он простой, как табуретка, в чем вы сейчас и убедитесь.

Получение странички из интернета

Как вы думаете, сколько строк кода нужно написать, чтобы скачать какой-нибудь текстовый файл из интернета и отобразить его содержимое на экране? 10? 100? 1000? А может быть, 5?

Код Примечание
Создает объект URL с путем к странице
Получает InputStream у интернет-объекта
Читает все байты и возвращает массив байт
Преобразуем массив в строку
Выводим строку на экран

На экране отобразится содержимое HTML-файла:

Вывод на экран

Напиши код, который будет считывать с клавиатуры ссылку на файл в интернете, скачивать его и сохранять во временный файл. Используй методы createTempFile(null, null) и write(Path, byte[]) класса Files, а также метод openStream() класса URL.

2. Класс URLConnection

Кроме простого чтения данных из интернета, мы еще можем и загружать туда данные. Загрузка данных — это куда более сложный процесс, чем считывание. Вам понадобится на несколько методов больше. Пример:


Получаем поток вывода
Выводим в него данные

Обратите внимание, что тут мы больше не вызываем метод url.openStream() . Вместо этого мы идем по более длинному пути:

  • Сначала мы устанавливаем стабильное двустороннее соединение с помощью метода URLConnection openConnection()
  • Затем получаем поток для отправки данных с помощью метода connection.getOutputStream() и отправляем данные серверу
  • Затем получаем поток для чтения данных с помощью метода connection.getInputStream() и начинаем читать из него данные.

Контроль ресурсов

Строго говоря, мы должны все потоки обернуть в try -with-resources для безопасной работы. А еще не помешало бы обернуть голые InputStream и OutputStream во что-нибудь более удобное. Например, в PrintStream и BufferedReader .

Если мы все это сделаем, наш код будет выглядеть как-то так:

3. Примеры работы с сетью

А давай-ка мы что-нибудь загрузим из интернета. И не просто загрузим, а сохраним на диск.

Например, давайте напишем программу, которая сохраняет на диск картинку с главной страницы Google.

В принципе ничего сложного. В самой простой интерпретации этот код будет выглядеть так:

Сохранение файла на диск

С помощью трех первых срок мы получаем поток данных от интернет-ресурса — от картинки.

В четвертой строке мы создаем имя файла, в который будем сохранять картинку. Имя может быть любым, однако расширение файла должно совпадать с расширением картинки в интернете. Так локальные программы просмотра картинок будут правильно ее открывать.

Ну и наконец, последняя строка — это один из методов copy класса Files . У класса Files их несколько. Этот метод, который мы использовали, принимает в качестве первого параметра источник данных — байтовый поток ( InputStream ), а в качестве второго параметра — имя файла, куда нужно записывать данные.

Теоретически, если бы URL картинки был коротким, этот код вообще можно было бы записать в одну строку:

Копирование данных из потока в файл

Писать так, конечно же, не нужно , однако этот пример демонстрирует, насколько удобные и мощные в Java потоки ввода-вывода.

URL обозначает унифицированный указатель ресурса и представляет ресурс во Всемирной компьютерной сети, такой как веб-страница или каталог FTP (протокол пересылки файлов).

В этом разделе указано о том, как писать Java-программы, которые взаимодействуют с URL. URL может быть разбит на части, как указано ниже:

Содержание

Конструкторы класса URL

Класс URL имеет несколько конструкторов для создания URL, включая следующие:

и описание
1public URL(String protocol, String host, int port, String file) throws MalformedURLException
public URL(URL context, String url) throws MalformedURLException
2public URL(String protocol, String host, String file) throws MalformedURLException
Идентичен предыдущему конструктору, за исключением того, что для данного протокола используется порт по умолчанию.
3public URL(String url) throws MalformedURLException
Создает URL путем заданной адресной строки.
4public URL(URL context, String url) throws MalformedURLException
Создает URL, анализируя аргументы URL и адресной строки.

Методы класса URL

Класс URL содержит много методов для доступа к различным частям представляемого URL. Некоторые из методов в классе URL включают следующее:

и описание
1public String getPath()
Возвращает путь URL.
2public String getQuery()
Возвращает часть запроса URL.
3public String getAuthority()
Возвращает полномочия URL.
4public int getPort()
Возвращает порт URL.
5public int getDefaultPort()
Возвращает порт по умолчанию протокола URL.
6public String getProtocol()
Возвращает протокол URL.
7public String getHost()
Возвращает хост URL.
8public String getHost()
Возвращает хост URL.
9public String getFile()
Возвращает имя файла URL.
10public String getRef()
Возвращает часть ссылки URL.
11public URLConnection openConnection() throws IOException
Открывает соединение с URL, позволяя клиенту взаимодействовать с ресурсом.

Пример

Следующая программа URLDemo демонстрирует различные части URL. URL вводится в командной строке, и программа URLDemo выводит данные каждой части данного URL.

Пробный запуск этой программы даст следующий результат:

Методы класса URLConnection

У класса подключения URL есть много методов для установки или определения информации о соединении, включая следующие:

и описание
1Object getContent()
Получает содержимое этого URL-соединения.
2Object getContent(Class[] classes)
Получает содержимое этого URL-соединения.
3String getContentEncoding()
Возвращает значение строки заголовка с кодировкой содержимого.
4int getContentLength()
Возвращает значение строки заголовка с длиной содержимого.
5String getContentType()
Возвращает значение строки заголовка с типом содержимого.
6int getLastModified()
Возвращает значение строки заголовка с последними изменениями.
7long getExpiration()
Возвращает значение строки заголовка, превышающее длину.
8long getIfModifiedSince()
Возвращает значение поля ifModifiedSince этого объекта.
9public void setDoInput(boolean input)
Передает true (истина), чтобы обозначить, что соединение будет использоваться для ввода. Значение по умолчанию - true, потому что клиенты обычно считывают из URL-соединения.
10public void setDoOutput(boolean output)
Передает true, чтобы обозначить, что соединение будет использоваться для вывода. Значение по умолчанию - false (ложь), поскольку многие типы URL не поддерживают запись.
11public InputStream getInputStream() throws IOException
Возвращает поток входных данных URL-соединения для считывания из ресурса.
12public OutputStream getOutputStream() throws IOException
Возвращает поток выходных данных URL-соединения для записи на ресурс.
13public URL getURL()
Возвращает URL, с которым связан данный объект URL-соединения.

Пример

Следующая программа URLConnectionDemo подключается к URL-адресу, введенному из командной строки.

Читайте также: