Kartinka.info

IT Новости


09ae9cb0
2 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Bufferedreader в java

Потоки 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

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

Программе в качестве параметра передается имя файла в командной строке. Переменная 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()).
Читать еще:  Java sql insert

Классы, производные от 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 имеет следующие конструкторы :

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

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

Класс Java.io.BufferedReader в Java

Считывает текст из потока ввода символов, буферизует символы, чтобы обеспечить эффективное чтение символов, массивов и строк.

  • Размер буфера может быть указан, или размер по умолчанию может быть использован. Значение по умолчанию достаточно велико для большинства целей.
  • Как правило, каждый запрос чтения, сделанный устройством чтения, вызывает соответствующий запрос чтения основного символа или потока байтов.
  • Поэтому желательно обернуть BufferedReader вокруг любого Reader, чьи операции read () могут быть дорогостоящими, например FileReaders и InputStreamReaders.
  • Программы, которые используют DataInputStreams для текстового ввода, могут быть локализованы путем замены каждого DataInputStream соответствующим BufferedReader.

Конструкторы:

  • BufferedReader (Reader in): создает буферный поток ввода символов, который использует размер буфера ввода по умолчанию.
  • BufferedReader (Reader in, int sz): Создает буферный поток ввода символов, который использует входной буфер указанного размера.

Методы:

  • void close (): закрывает поток и освобождает любые связанные с ним системные ресурсы. Как только поток будет закрыт, дальнейшие вызовы read (), ready (), mark (), reset () или skip () вызовут IOException , Закрытие ранее закрытого потока не имеет никакого эффекта.
  • void mark (int readAheadLimit): отмечает текущую позицию в потоке. Последующие вызовы reset () будут пытаться переместить поток в эту точку.
  • boolean markSupported (): сообщает, поддерживает ли этот поток операцию mark (), что он и делает.
  • int read (): читает один символ.
  • int read (char [] cbuf, int off, int len): считывает символы в часть массива.
    Этот метод реализует общий контракт соответствующего метода чтения класса Reader. В качестве дополнительного удобства он пытается прочитать как можно больше символов, многократно вызывая метод read базового потока. Это повторное чтение продолжается до тех пор, пока не выполнится одно из следующих условий:
    • Указанное количество символов было прочитано,
    • Метод чтения базового потока возвращает -1, указывая конец файла, или
    • Метод ready базового потока возвращает false, указывая, что дальнейшие запросы ввода будут блокироваться.

    Если первое чтение в основном потоке возвращает -1, чтобы указать конец файла, тогда этот метод возвращает -1. В противном случае этот метод возвращает количество фактически прочитанных символов.

  • String readLine (): читает строку текста. Считается, что строка завершается любым из следующих: перевод строки (‘/ n’), возврат каретки (‘/ r’) или возврат каретки, за которым сразу следует перевод строки.
  • boolean ready (): сообщает, готов ли этот поток для чтения.
  • void reset (): Сбрасывает поток до самой последней отметки.
  • long skip (long n): пропускает символы.

// Java-программа, демонстрирующая методы BufferedReader

public static void main(String[] args) throws IOException

FileReader fr = new FileReader( «file.txt» );

BufferedReader br = new BufferedReader(fr);

char c[]= new char [ 20 ];

// иллюстрируем метод markSupported ()

System.out.println( «mark() method is supported» );

// иллюстрирующий метод маркировки

* Это первая строка

это вторая строка

// пропускаем 8 символов

// иллюстрируем метод ready ()

// иллюстрируем метод readLine ()

// иллюстрируем чтение (char c [], int off, int len)

for ( int i = 0 ; i 20 ; i++)

// иллюстрирующий метод reset ()

for ( int i = 0 ; i 8 ; i++)

// иллюстрирующий метод read ()

System.out.print(( char )br.read());

Выход :

Эта статья предоставлена Nishant Sharma . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Why use BufferedReader and BufferedWriter Classses in Java

Both BufferedReader and BufferedWriter in java are >buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

Читать еще:  Пишем игру на javascript

For unbuffered I/O stream, each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive. This means that instead of using BufferedReader, one can use the Scanner >BufferedWriter, one can use PrintWriter.

BufferedReader is a class in Java that reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, lines and arrays. The buffer size may be specified. If not, the default size, which is predefined, may be used.

In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream. It is therefore good practice to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,

will buffer the input from the specified file. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.

A BufferedWriter on the other hand is a java class that writes text to a character-output stream, while buffering characters so as to provide for the efficient writing of single characters, strings and arrays.

A newLine() method is provided, which uses the platform’s own notion of line separator as defined by the system property line.separator. Calling this method to terminate each output line is therefore preferred to writing a newline character directly.

In most occasions, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is good practice to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. For example,

will buffer the PrintWriter’s output to the file. Without buffering, each invocation of a print() method would cause characters to be converted into bytes that would then be written immediately to the file, which can be very inefficient.

Both BufferedReader and BufferedWriter are used in order to achieve greater efficiency through use of buffers. A data buffer is generally a region in memory that is temporarily used. Instructing a BufferedWriter to write on a file, it does not do it directly. Rather, it stores what you want it to write in a buffer and writes it onto the file when you tell it to perform a flush operation. Flushing is the operation that tells the BufferedWriter to write everything onto the output file. Using a buffer is what makes both BufferedReader and BufferedWriter fast and efficient.

It is recommended to use buffered I/O streams as opposed to Scanner and PrintWriter classes because of the following reasons:

Gu >Last modified: February 12, 2020

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

In the 9 years of running Baeldung, I’ve never, ever done a «sale».
But. we’ve also not been through anything like this pandemic either.
And, if making my courses more affordable for a while is going to help a company stay in business, or a developer land a new job, make rent or be able to provide for their family — then it’s well worth doing.
Effective immediately, all Baeldung courses are 33% off their normal prices!
You’ll find all three courses in the menu, above, or here.

1. Overview

BufferedReader is a class which simplifies reading text from a character input stream. It buffers the characters in order to enable efficient reading of text data.

In this tutorial, we’re going to look at how to use the BufferedReader class.

2. When to Use BufferedReader

In general, BufferedReader comes in handy if we want to read text from any kind of input source whether that be files, sockets, or something else.

Simply put, it enables us to minimize the number of I/O operations by reading chunks of characters and storing them in an internal buffer. While the buffer has data, the reader will read from it instead of directly from the underlying stream.

2.1. Buffering Another Reader

Like most of the Java I/O classes, BufferedReader implements Decorator pattern, meaning it expects a Reader in its constructor. In this way, it enables us to flexibly extend an instance of a Reader implementation with buffering functionality:

But, if buffering doesn’t matter to us we could just use a FileReader directly:

In addition to buffering, BufferedReader also provides some nice helper functions for reading files line-by-line. So, even though it may appear simpler to use FileReader directly, BufferedReader can be a big help.

2.2. Buffering a Stream

In general, we can configure BufferedReader to take any kind of input stream as an underlying source. We can do it using InputStreamReader and wrapping it in the constructor:

In the above example, we are reading from System.in which typically corresponds to the input from the keyboard. Similarly, we could pass an input stream for reading from a socket, file or any imaginable type of textual input. The only prerequisite is that there is a suitable InputStream implementation for it.

Читать еще:  Locale english java

2.3. BufferedReader vs Scanner

As an alternative, we could use the Scanner class to achieve the same functionality as with BufferedReader.

However, there are significant differences between these two classes which can make them either more or less convenient for us, depending on our use case:

  • BufferedReader is synchronized (thread-safe) while Scanner is not
  • Scanner can parse primitive types and strings using regular expressions
  • BufferedReader allows for changing the size of the buffer while Scanner has a fixed buffer size
  • BufferedReader has a larger default buffer size
  • Scanner hides IOException, while BufferedReader forces us to handle it
  • BufferedReader is usually faster than Scanner because it only reads the data without parsing it

With these in mind, if we are parsing individual tokens in a file, then Scanner will feel a bit more natural than BufferedReader. But, just reading a line at a time is where BufferedReader shines.

If needed, we also have a guide on Scanner as well.

3. Reading Text With BufferedReader

Let’s go through the entire process of building, using and destroying a BufferReader properly to read from a text file.

3.1. Initializing a BufferedReader

Firstly, let’s create a BufferedReader using its BufferedReader(Reader) constructor:

Wrapping the FileReader like this is a nice way to add buffering as an aspect to other readers.

By default, this will use a buffer of 8 KB. However, if we want to buffer smaller or larger blocks, we can use the BufferedReader(Reader, int) constructor:

This will set the buffer size to 16384 bytes (16 KB).

The optimal buffer size depends on factors like the type of the input stream and the hardware on which the code is running. For this reason, to achieve the ideal buffer size, we have to find it ourselves by experimenting.

It’s best to use powers of 2 as buffer size since most hardware devices have a power of 2 as the block size.

Finally, there is one more handy way to create a BufferedReader using the Files helper class from the java.nio API:

Creating it like this is a nice way to buffer if we want to read a file because we don’t have to manually create a FileReader first and then wrap it.

3.2. Reading Line-by-Line

Next, let’s read the content of the file using the readLine method:

We can do the same thing as above using the lines method introduced in Java 8 a bit more simply:

3.3. Closing the Stream

After using the BufferedReader, we have to call its close() method to release any system resources associated with it. This is done automatically if we use a try-with-resources block:

4. Other Useful Methods

Now let’s focus on various useful methods available in BufferedReader.

4.1. Reading a Single Character

We can use the read() method to read a single character. Let’s read the whole content character-by-character until the end of the stream:

This will read the characters (returned as ASCII values), cast them to char and append them to the result. We repeat this until the end of the stream, which is indicated by the response value -1 from the read() method.

4.2. Reading Multiple Characters

If we want to read multiple characters at once, we can use the method read(char[] cbuf, int off, int len):

In the above code example, we’ll read up to 5 characters into a char array and construct a string from it. In the case that no characters were read in our read attempt (i.e. we’ve reached the end of the stream), we’ll simply return an empty string.

4.3. Skipping Characters

We can also skip a given number of characters by calling the skip(long n) method:

In the above example, we read from an input string which contains numbers separated by two underscores. In order to construct a string containing only the numbers, we are skipping the underscores by calling the skip method.

4.4. mark and reset

We can use the mark(int readAheadLimit) and reset() methods to mark some position in the stream and return to it later. As a somewhat contrived example, let’s use mark() and reset() to ignore all whitespaces at the beginning of a stream:

In the above example, we use the mark() method to mark the position we just read. Giving it a value of 1 means only the code will remember the mark for one character forward. It’s handy here because, once we see our first non-whitespace character, we can go back and re-read that character without needing to reprocess the whole stream. Without having a mark, we’d lose the L in our final string.

Note that because mark() can throw an UnsupportedOperationException, it’s pretty common to associate markSupported() with code that invokes mark(). Though, we don’t actually need it here. That’s because markSupported() always returns true for BufferedReader.

Of course, we might be able to do the above a bit more elegantly in other ways, and indeed mark and reset aren’t very typical methods. They certainly come in handy, though, when there is a need to look ahead.

5. Conclusion

In this quick tutorial, we’ve learned how to read character input streams on a practical example using BufferedReader.

Finally, the source code for the examples is available over on Github.

Ссылка на основную публикацию
×
×