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

OutputStreamWriter против FileWriter

Я не понимаю разницы между этими двумя классами. Когда вы будете использовать один над одним? Я знаю, что FileWriter может выводить символы в файл, но так же может и OutputStreamWriter, насколько я знаю. Вот какой код, который я тестировал, и они, похоже, работают одинаково, я не добавляю материал для обработки исключений, но давайте просто предположим его там.

FileWriter writer = new FileWriter("C:\\Users\\owner\\Desktop\\demo.txt");
writer.write("hello");
writer.close();

Я также пробовал этот код:

File file = new File("C:\\Users\\owner\\Desktop\\demo.txt");
os = new OutputStreamWriter(new FileOutputStream(file));
os.write("hello");
os.close();

Оба эти, похоже, работают одинаково для меня. Единственный раз, когда случается что-то странное, я пытаюсь поместить значение int в метод write(). Для примера FileWriter мой demo.txt полностью пуст. Для примера OutputStreamWriter я получаю некоторые странные символы в текстовом файле. Я читаю java-книгу, и единственным объяснением, которое я получаю для OutputStreamWriter, является то, что он "преобразует поток символов в поток байтов", поэтому не следует ли мне видеть некоторые байты в моем текстовом файле во втором примере?

Некоторые разъяснения были бы с благодарностью.

4b9b3361

Ответ 1

XXXInputStream и XXXOutputStream (где XXX меняется, есть множество опций) для работы с 8-битными байтами. Например, OutputStream.write(byte[] c);

XXXWriter или XXXReader работают с 16-разрядными символами. Например, Reader.read(char[] cbuf).

OutputStreamWriter преобразует OutputStream в Writer. Как вы, возможно, догадались, InputStreamReader преобразует из InputStream в Reader. Я не знаю о каких-либо классах, которые делают обратное, т.е. Конвертируют Reader в InputStream.

FileWriter - это Writer, который ведет переговоры с файлами. Поскольку Java String внутренне использует символы (16 бит, чтобы они могли обрабатывать Unicode), FileWriter является естественным классом для использования с Unicode Strings.

FileOutputStream - это OutputStream для записи байтов в файл. OutputStreams не принимают символы (или строки). Обернув его в OutputStreamWriter, теперь у вас есть Writer, который принимает строки.

Теперь, реальный вопрос, когда вы используете Reader/Writer и когда Stream? Я использовал Java в течение многих лет, и иногда я тоже смущаюсь. Я считаю правильным следующее:

Handy Guide - как решить, что использовать:

  • Если вы имеете дело с двоичными данными (например, с изображением), используйте Streams.
  • Если вы используете символы Unicode, отличные от ASCII, например. Китайский, использование Читатели/писатели.
  • Если вы используете обычный текст ASCII (традиционные 0-127 символов), вы можете (обычно) использовать либо.

Некоторые другие ссылки:

входной поток и считыватель в Java IO

InputStream vs InputStreamReader

Ответ 2

Фактически нет никакой разницы, FileWriter - это просто класс удобства. Он расширяет OutputStreamWriter и создает необходимый FileOutputStream.

Относительно write(int): этот метод записывает один символ с указанным кодовым пунктом в поток, он не записывает текстовое представление числового значения.

Что касается пустого файла, обратите внимание, что вы всегда должны очищать буфер, если хотите, чтобы все, что вы написали, сбросило в основной магазин (будь то файл или сетевой поток или что бы вы ни думали). Просто позвоните os.flush() после записи, это должно сделать это.
EDIT: Как правильно сказал Thilo, закрытие потока должно уже очистить его (и все базовые потоки).

И последнее, но не менее важное: вы должны почти всегда явно указывать кодировку/кодировку, которую вы хотите записать в Writer. Писатели пишут символы, а OutputStreams записывают байты, поэтому вам нужно указать, как эти символы должны быть закодированы в байты. Если вы не укажете кодировку, используется система по умолчанию, которая может быть не такой, какой вы хотите.

Ответ 3

Это от здесь

В java.io вы либо выполняете байты ввода-вывода, либо символ IO. Байт IO может использоваться для любой формы данных без какой-либо интерпретации того, что эти данные представляет. Символ IO предназначен для, ну, информации, которая представленные как последовательности символов.

Для байта IO мы имеем различные типы классов InputStream/OutputStream как FileOutputStream из вашего примера 1). Для символьных данных имеют различные формы классов Reader/Writer, таких как FileWriter, из ваш пример. Буферизация может быть выполнена в обоих случаях, BufferedWriter и BufferedOutputStream.

Для символа IO символы в какой-то момент должны быть преобразованы в байтовые данные, используя некоторую форму кодирования. FileWriter делает это для вы, поэтому он имеет конструктор, который принимает кодировку вдоль с именем файла. Обычные кодировки включают UTF-8, UTF-16 и US-ASCII.

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

Если вы опускаете явные спецификации кодирования как FileWriter, так и ByteArrayOutputStream будет использовать кодировку по умолчанию для вашей платформы. Это должно быть очень осторожным, поскольку оно будет разные JVM.

Ответ 4

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

Принудительное кодирование для UTF-8 следующим образом:

OutputStreamWriter osw = new OutputStreamWriter(
    new FileOutputStream(exportPath),
    Charset.forName("UTF-8").newEncoder() 
);