— И это снова я.
— Привет, Элли!
— Сегодня я хочу тебе подробно рассказать про BufferedReader и BufferedWriter.
— Так ты мне уже рассказывала все про них. Ну ничего там сложного нет.
— Ок. Расскажи, как работает BufferedReader.
— BufferedReader — это как переходник в розетке с 110 к 220 вольт.
В конструктор объекта BufferedReader обязательно нужно передать объект Reader, из которого он будет читать данные. Объект BufferedReader читает из Reader’а данные большими кусками и хранит их у себя внутри в буфере. Поэтому чтение из пары BufferedReader+Reader быстрее, чем прямо из Reader.
— Верно. А BufferedWriter?
— Тут тоже все просто. Когда мы пишем в FileWriter, например, то данные сразу записываются на диск. Если мы часто пишем небольшие данные, то происходит много обращений к диску, что замедляет работу программы. А если мы используем BufferedWriter в качестве «переходника», то операция записи на диск ускорится. BufferedWriter, при записи в него, сохраняет переданные данные во внутреннем буфере, а когда буфер заполняется – пишет данные во Writer одним большим куском. Это гораздо быстрее.
— Гм. Все верно. А что ты забыл?
— После окончания записи у объекта BufferedWriter надо вызвать метод flush(), чтобы он записал данные из буфера во Writer, которые еще не записаны, т.е. буфер не заполнен до конца.
— А кроме того?
— А кроме того, пока буфер еще не записан во Writer, данные можно удалить и/или заменить на другие.
— Амиго! Я поражена! Да ты просто эксперт. Ладно, тогда я расскажу тебе о новых классах: ByteArrayStream, PrintStream.
Итак, ByteArrayInputStream и ByteArrayOutputStream.
Эти классы по сути чем-то похожи на StringReader и StringWriter. Только StringReader читал символы (char) из строки (String), а ByteArrayInputStream читает байты из массива байт (ByteArray).
StringWriter писал символы (char) в строку, а ByteArrayOutputStream пишет байты в массив байт у него внутри. При записи в StringWriter строка внутри него удлинялась, а при записи в ByteArrayOutputStream его внутренний массив байт тоже динамически расширяется.
Вот пример, который выводит в консоль полученную строку:
public static void main (String[] args) throws Exception
{
String test = "Hi!\n My name is Richard\n I'm a photographer\n";
StringReader reader = new StringReader(test);
StringWriter writer = new StringWriter();
executor(reader, writer);
String result = writer.toString();
System.out.println("Результат: "+result);
}
public static void executor(Reader reader, Writer writer) throws Exception
{
BufferedReader br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
writer.write(line + '\n');
}
}
Вот как он будет выглядеть, если тут работать не с символами, а с байтами:
public static void main (String[] args) throws Exception
{
String test = "Hi!\n My name is Richard\n I'm a photographer\n";
InputStream inputStream = new ByteArrayInputStream(test.getBytes());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
executor(inputStream, outputStream);
String result = new String(outputStream.toByteArray());
System.out.println("Результат: "+result);
}
public static void executor(InputStream inputStream, OutputStream outputStream) throws Exception
{
BufferedInputStream bis = new BufferedInputStream(inputStream);
while (bis.available() > 0)
{
int data = bis.read();
outputStream.write(data);
}
}
Тут все аналогично примеру выше. Вместо String – ByteArray. Вместо Reader – InputStream, вместо Writer – OutputStream.
Единственные еще два момента – это преобразование строки в массив байт и обратно. Как ты видишь, это делается довольно несложно:
public static void main (String[] args) throws Exception
{
String test = "Hi!\n My name is Richard\n I'm a photographer\n";
byte[] array = test.getBytes();
String result = new String(array);
System.out.println("Результат: "+result);
}
Чтобы получить байты, которые уже добавлены в ByteArrayOutputStream, надо вызвать метод toByteArray().
— Ага. Аналогия с StringReader/StringWriter довольно сильная, особенно когда ты мне ее показала. Спасибо, Элли, действительно интересный урок.
— Куда это ты спешишь? У меня есть еще небольшой подарок – хочу рассказать тебе про класс PrintStream.
— PrintStream? В первый раз слышу о таком классе.
— Ага. Особенно, если не считать, что ты им пользуешься с первого дня, когда ты начал изучать Java. Помнишь System.out? так вот – System.out – это статическая переменная класса System типа… PrintStream! Именно оттуда растут ноги всех этих print, println и т.д.
— Ого. Как интересно. Я как-то ни разу и не задумывался. Расскажи подробнее.
— Гуд. Тогда слушай. Класс PrintStream был придуман для читабельного вывода информации. Он практически весь состоит из методов print и println. См. таблицу:
Методы | Методы |
---|---|
void print(boolean b) |
void println(boolean b) |
void print(char c) |
void println(char c) |
void print(int c) |
void println(int c) |
void print(long c) |
void println(long c) |
void print(float c) |
void println(float c) |
void print(double c) |
void println(double c) |
void print(char[] c) |
void println(char[] c) |
void print(String c) |
void println(String c) |
void print(Object obj) |
void println(Object obj) |
|
void println() |
PrintStream format (String format, Object ... args) |
|
PrintStream format (Locale l, String format, Object ... args) |
Также есть несколько методов format, чтобы можно было выводить данные на основе шаблона. Пример:
String name = "Kolan";
int age = 25;
System.out.format("My name is %s. My age is %d.", name, age);
My name is Kolan. My age is 25.
— Ага, помню, мы уже когда-то разбирали метод format у класса String.
— На этом все.
— Спасибо, Элли.