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, является то, что он "преобразует поток символов в поток байтов", поэтому не следует ли мне видеть некоторые байты в моем текстовом файле во втором примере?
Некоторые разъяснения были бы с благодарностью.
Ответы
Ответ 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()
);