Можете ли вы создать FileWriter или BufferedWriter непосредственно из InputStream? - PullRequest
1 голос
/ 09 февраля 2020

Поэтому я использую Java. net .URL, чтобы получить соединение с URL-адресом, содержащим некоторые данные xml (.atom?) Для анализа для записи в локальный файл.

Это многому меня учит о чтении и письме. Вот мой текущий процесс:

  1. создать объект URL
  2. получить «поток»
  3. Создать InputStreamReader
  4. Обернуть ISR в Buffered Reader
  5. Создание FileWriter
  6. Перенос FW в Bufferedwriter
  7. строка за строкой, чтение и запись
  8. , закрытие BufferedWriter.

Оно работает! Я узнал разницу между читателем, BufferedReader, писателем и BfferedWriter. Замечательно. Я немного неясен с потоками, но пока это нормально.

Однако мне было интересно, есть ли способ создать BufferedWriter непосредственно из InputStream, чтобы сохранить все эти средние шаги.

  1. Создать объект URL
  2. получить «Поток»
  3. перейти прямо к BufferedWriter ()
  4. записать в локальный файл.
  5. закройте BufferedWriter

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

Ответы [ 3 ]

3 голосов
/ 10 февраля 2020

Можно ли создать FileWriter или BufferedWriter непосредственно из InputStream?

Нет. Как вы заметили, BufferedWriter оборачивает другой экземпляр Writer. Это Java типичный пример шаблона Decorator .

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

С другой стороны, в дополнение к тому, что вы многому научились в чтении и письме, теперь это упражнение научило вас и шаблонам проектирования!

1 голос
/ 11 февраля 2020

Чтобы ответить на ваш главный вопрос: Нет, вы не можете go напрямую с InputStream / OutputStream до BufferedReader / BufferedWriter. Проблема в том, что вам нужен класс, который может переводить из потока ввода / вывода, который имеет дело непосредственно с байтами, в устройство чтения / записи, которое имеет дело с символами (то есть путем декодирования байтов в символы и наоборот). Как указывает @ jaco0646 ответ , это один из минусов шаблона декоратора. Конечно, вы можете сделать служебный метод:

public static BufferedReader toBufferedReader(InputStream stream, Charset charset) {
  return new BufferedReader(new InputStreamReader(stream, charset));
}

, чтобы сделать ваш другой код короче. Хотя я уверен, что уже есть библиотека, которая обеспечивает это (например, может быть Commons IO или Guava ).

Это все, как говорится, вы не Похоже, нужен читатель или писатель. Ваш вопрос указывает, и вы позже подтверждаете в комментарии , что вы просто загружаете данные непосредственно в файл. Это означает, что вам не нужно декодировать байты в символы только для немедленного кодирования символов обратно в байты. Вам просто нужно перенести байты с InputStream на OutputStream напрямую. Вот несколько примеров (оставаясь в JDK):

Копирование байтов вручную с использованием буфера

public static void copyUrlToFile(URL url, File file) throws IOException {
  try (InputStream input = url.openStream();
      OutputStream output = new FileOutputStream(file)) {

    byte[] buffer = new byte[1024 * 8]; // 8 KiB buffer
    int read;
    while ((read = input.read(buffer)) != -1) {
      output.write(buffer, 0, read);
    }
  }
}

Можно также использовать Path и Files#newOutputStream(Path,OpenOption...) вместо File и FileOutputStream.

Использование InputStream#transferTo(OutputStream) (Java 9 +)

public static void copyUrlToFile(URL url, File file) throws IOException {
  try (InputStream input = url.openStream();
      OutputStream output = new FileOutputStream(file)) {
    input.transferTo(output);
  }
}

Использование Files#copy(InputStream,Path,CopyOption...)

public static void copyUrlToFile(URL url, Path file) throws IOException {
  try (InputStream input = url.openStream()) {
    Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
  }
}

Обратите внимание, что при использовании NIO вы можете открывать буферизованные устройства чтения и записи для файлов, непосредственно используя Files#newBufferedReader(Path) и Files#newBufferedWriter(Path,OpenOption...) соответственно.

1 голос
/ 10 февраля 2020

Что-то вроде следующего?

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;

public class Main {
    public static void main(String[] args) {
        try (InputStream inputStream = URI.create("https://www.example.com/").toURL().openStream()) {
            try (FileOutputStream outputStream = new FileOutputStream(new File("output.txt"))) {
                int read;
                byte[] bytes = new byte[1024];
                while ((read = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...