Потоки Reader и Writer

Абстрактные классы Reader и Writer являются символьными потоками.

Абстрактный класс Reader

Класс Reader обеспечивает поддержку символьного потока чтения аналогично тому, как это делает InputStream, реализующий модель байтового потока ввода. Методы Reader схожи с теми, которые объявлены в составе InputStream.

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

МетодОписание
abstract void close() throws IOException Закрытие ранее открытого потока чтения. Метод используется для высвобождения ресурсов, связанных с потоком (таких как дескрипторы открытых файлов). Любые попытки обращения к закрытому потоку приводят к выбрасыванию исключения типа IOException, но повторное закрытие потока эффектов не вызывает.
void mark(int limit) Размещение метки в текущей позиции входного потока
boolean markSupported() Функция проверки поддержки потоком методов mark() и reset()
boolean ready() Функция проверки готовности объекта для чтения данных, т.е. в нем существует хотя бы один доступный символ. Следует заметить, что результат, равный false, отнюдь не свидетельствует о том, что очередной вызов read приведет к возникновению блокировки, поскольку в промежутке между обращениями к ready и read в поток может поступить очередная порция данных.
void reset() Сброс указателя ввода в ранее установленную позицию метки.
long skip(long count) Функция пропуска указанного в параметре count количества символов ввода. Возвращает количество действительно пропущенных символов. Значение count не должно быть отрицательным.
int read() throws lOException Чтение одного символа данных в виде целого числа в диапазоне от 0 до 65535. Если символов, готовых для чтения, нет ввиду достижения конца потока, то возвращается значение -1. Метод выполняет блокировку до тех пор, пока имеются доступные для чтения символы, не достигнут конец потока либо не выброшено исключение.
abstract int read(char[] buf, int offset, int count) throws lOException Чтение символов и сохранение их в массиве buf типа char. Максимальное количество читаемых символов определяется значением count. Символы записываются в массив, начиная с смещение offset. Содержимое всех остальных элементов массива buf остается неизменным. Метод возвращает количество фактически считанных символов.
Если достигнут конец потока и не считан ни один символ, возвращается -1. Если значение count равно нулю, чтение не производится и возвращается 0.
Метод выполняет блокировку до тех пор, пока имеются доступные для чтения символы не достигнут конец потока либо не выброшено исключение.
int read(char[] buf) throws IOException Метод аналогичен предыдущему при условии, offset = 0, count = buf.length.

При реализации Reader требуется, чтобы производный класс (наследник) обеспечил практическое воплощение варианта метода read, осуществляющего чтение данных в массив символов, и версии метода close. Во многих случаях, однако, производительность операций может быть улучшена за счет переопределения в производных классах и других методов.

Наследники класса Reader

  • BufferedReader - буферизированный входной символьный поток; увеличивает производительность за счёт буферизации ввода;
  • CharArrayReader - входной поток чтения символьного массива;
  • FileReader - входной поток чтения содержимого файла; в конструкторе класса нужно указать либо путь к файлу, либо объект типа File;
  • FilterReader - фильтрующий читатель;
  • InputStreamReader - входной поток, транслирующий байты в символы;
  • LineNumberReader - входной поток, подсчитывающий строки;
  • PipedReader - входной канал;
  • PushbackReader - входной поток, позволяющий возвращать символы обратно в поток;
  • StringReader - входной поток, читающий из строки.

Класс BufferedReader

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

BufferedReader имеет следующие конструкторы :

BufferedReader(Reader in) 
BufferedReader(Reader in, int sz) 

Примеры BufferedReader

BufferedReader in = new BufferedReader(new FileReader("foo.in"));
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

В качестве примера рассмотрим программу подсчета общего количества символов и числа пробелов в символьном потоке чтения:

import java.io.*;

class CountSpaces
{
    public static void main(String[]  args) throws IOException
    {
        int chr; 
        int total; 
        int spaces = 0;

        try {
            Reader in = null;
            if (args.length == 0)
                in = new InputStreamReader(System.in);
            else
                in = new FileReader(args[0]);
            for (total = 0; (chr = in.read()) != -1; total++) {
                if (Character.isWhitespace((char) chr))
                    spaces++;
            }
            System.out.println("Количество символов : " + total + "\nКоличество пробелов : " + spaces);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Программе в качестве параметра передается имя файла в командной строке. Переменная in представляет символьный поток чтения. Если имя файла не задано, то используется стандартный поток ввода, System.in, после "вложения" его в объект типа InputStreamReader, который выполняет преобразование байтового потока ввода в символьный поток чтения. В противном случае создается объект типа FileReader, расширяющего класс Reader.

В цикле for подсчитывается общее количество символов в файле. Кроме этого, с использованием метода isWhitespace класса Character выявляются символы пробела и вычисляется их количество, а затем на экран выводится результат.

Абстрактный класс Writer

Абстрактный класс Writer обеспечивает поддержку символьного потока записи аналогично тому, как это делает OutputStream, реализующий модель байтового потока вывода. Многие методы Writer схожи с теми, которые объявлены в OutputStream; помимо этого, в классе Writer предусмотрены некоторые другие полезные версии метода write.

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

Все методы класса вызывают исключение IOException при возникновении ошибки.

МетодОписание
append(char c) Добавление символа в конец вызывающего выходного потока.
abstract void close() throws lOException Закрытие ранее открытого поток записи; при необходимости выполняется сброс потока. Метод используется для высвобождения ресурсов, связанных с потоком (таких как дескрипторы открытых файлов). Любые попытки обращения к закрытому потоку приводят к выбрасыванию исключения типа lOException, но повторное закрытие потока эффектов не вызывает.
abstract void flush() Сброс потока. Если поток сохраняет в промежуточном буфере некоторое число символов, переданных методами write различных версий, flush провоцирует выполнение операции непосредственной записи данных в объект-получатель. Затем, если получателем является другой поток, тот в свою очередь также сбрасывается. Таким образом, единственный вызов flush приводит к сбросу всех буферов в цепочке взаимосвязанных потоков. Если поток не относится к категории буферизованных, никакие действия не выполняются.
void write(int char) throws lOException Запись символа в выходной поток. Метод выполняет блокировку потока до тех пор, пока символ не будет записан.
abstract void write(char[] buf, int offset, int count) throws lOException Запись count символов массива buf, начиная с элемента buf [offset]. Метод выполняет блокировку до тех пор, пока символы не будут записаны.
void write(char[] buf) throws lOException Метод аналогичен предыдущему при условии offset = 0 и count = buf.length.
void write(String string, int offset, int count) throws lOException Запись count символов строки string, начиная с символа string.charAt(offset).
void write(String string) throws lOException Метод аналогичен предыдущему при условии offset = 0 и count = string.length()).

Классы, производные от Writer, должны реализовать вариант метода write, связанного с записью символов из части массива, а также методов close и flush. Все остальные методы Writer основаны на трех методах, названных выше. Это отличает Writer от класса OutputStream, в котором в качестве базового метода вывода предусмотрен вариант write, осуществляющий вывод одного байта, а для методов flush и close предложены реализации по умолчанию.

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

Наследники класса Writer

  • BufferedWriter - буферизированный выходной символьный поток; позволяет повысить производительность за счёт снижения количества операций физической записи в выходное устройство;
  • CharArrayWriter - выходной поток, который пишет в символьный массив;
  • FileWriter - выходной поток, пишущий в файл; в конструкторе можно определить вывод в конец файла. Создание объекта не зависит от наличия файла, он будет создан в случае необходимости. Если файл существует и он доступен только для чтения, то передаётся исключение IOException
  • FilterWriter - фильтрующий писатель
  • OutputStreamWriter -выходной поток, транслирующий байты в символы
  • PipedWriter - выходной канал
  • PrintWriter - выходной поток, включающий методы print() и println()
  • StringWriter - выходной поток, пишущий в строку

Класс BufferedWriter

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

BufferedWriter имеет следующие конструкторы :

BufferedWriter(Writer out) 
BufferedWriter(Writer out, int size)

В качестве параметра out конструктор BufferedWriter принимает поток вывода, в который надо осуществить запись. Второй параметр size указывает на размер буфера.

Пример использования классов FileWriter и BufferedWriter :

package examples;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.BufferedWriter;

public class WriteToFileExample
{
    public static void main(String[] args)
    {
        try {
            String content = "Данную строку запишем в файл";
            File file = new File("C:/someDir/filename.txt");

            // Если файл не существует, то создадим его
            if (!file.exists())
                file.createNewFile();

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();

            System.out.println("Запись завершена");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  Рейтинг@Mail.ru