что делает flush java

Когда/почему вызывать System.out.flush() в Java

Почему некоторые потоки необходимо очищать ( FileOutputStream и потоки из сокетов), в то время как стандартный выходной поток не работает?

Что-то вроде этого заставляет меня задаться вопросом, является ли просто вызов System.out.println() независимым от платформы, поскольку некоторые системы могут понадобиться вам для очистки потока.

ОТВЕТЫ

Ответ 1

Таким образом, описанный вами случай println явно обрабатывается, а случай write с byte[] также гарантированно очищается, потому что он подпадает под «всякий раз, когда байт-массив написан».

Если вы замените System.out на System.setOut и не будете использовать поток автозаполнения, тогда вам нужно будет очистить его, как и любой другой поток.

Ответ 2

Необязательно, a PrintStream может быть создан для автоматической смены; это означает, что метод flush автоматически вызывается после записи байтового массива, вызывается один из методов println или записывается символ новой строки или байта ( ‘\n’ ).

Хотя я не вижу в нем явно упоминания, я понимаю, что System.out выполнит эту автоматическую промывку.

Ответ 3

Если вы не можете дождаться появления элемента, сбросьте поток.

Когда JVM идет вниз, а не очистка потока, он рискует потерять элемент в буфере дисплея, что может сделать разумное сообщение об ошибке, сообщающее вам, почему JVM потерял навсегда. Это делает отладку гораздо более сложной, как люди тогда склонны говорить: «но она не попала сюда, потому что она напечатала бы это».

Источник

Система ввода/вывода

Java имеет в своём составе множество классов, связанных с вводом/выводом данных. Рассмотрим некоторые из них.

Класс File

В отличие от большинства классов ввода/вывода, класс File работает не с потоками, а непосредственно с файлами. Данный класс позволяет получить информацию о файле: права доступа, время и дата создания, путь к каталогу. А также осуществлять навигацию по иерархиям подкаталогов.

Подробнее о классе java.io.File

Поток

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

За ввод и вывод отвечают разные классы Java. Классы, производные от базовых классов InputStream или Reader, имеют методы с именами read() для чтения отдельных байтов или массива байтов (отвечают за ввод данных). Классы, производные от классов OutputStream или Write, имеют методы с именами write() для записи одиночных байтов или массива байтов (отвечают за вывод данных).

Подробнее о классе InputStream

Класс OutputStream

В этой категории находятся классы, определяющие, куда направляются ваши данные: в массив байтов (но не напрямую в String; предполагается что вы сможете создать их из массива байтов), в файл или канал.

BufferedOutputStream Буферизированный выходной поток ByteArrayOutputStream Создает буфер в памяти. Все данные, посылаемые в этот поток, размещаются в созданном буфере DataOutputStream Выходной поток, включающий методы для записи стандартных типов данных Java FileOutputStream Отправка данных в файл на диске. Реализация класса OutputStream ObjectOutputStream Выходной поток для объектов PipedOutputStream Реализует понятие выходного канала. FilterOutputStream Абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства.

BufferedOutputStream

Класс BufferedOutputStream не сильно отличается от класса OutputStream, за исключением дополнительного метода flush(), используемого для обеспечения записи данных в буферизируемый поток. Буферы вывода нужно для повышения производительности.

ByteArrayOutputStream

Класс ByteArrayOutputStream использует байтовый массив в выходном потоке. Метод close() можно не вызывать.

DataOutputStream

Класс DataOutputStream позволяет писать элементарные данные в поток через интерфейс DataOutput, который определяет методы, преобразующие элементарные значения в форму последовательности байтов. Такие потоки облегчают сохранение в файле двоичных данных.

Класс DataOutputStream расширяет класс FilterOutputStream, который в свою очередь, расширяет класс OutputStream.

Методы интерфейса DataOutput:

FileOutputStream

Класс FileOutputStream создаёт объект класса OutputStream, который можно использовать для записи байтов в файл. Создание нового объекта не зависит от того, существует ли заданный файл, так как он создаёт его перед открытием. В случае попытки открытия файла, доступного только для чтения, будет передано исключение.

Классы символьных потоков

Символьные потоки имеют два основных абстрактных класса Reader и Writer, управляющие потоками символов Unicode.

Reader

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

Читайте также:  что делать если кошка рыгает и поносит

Класс BufferedReader

Класс BufferedReader увеличивает производительность за счёт буферизации ввода.

Класс CharArrayReader

Класс CharArrayReader использует символьный массив в качестве источника.

Класс FileReader

Класс FileReader, производный от класса Reader, можно использовать для чтения содержимого файла. В конструкторе класса нужно указать либо путь к файлу, либо объект типа File.

Writer

Класс BufferedWriter

Класс CharArrayWriter

Класс CharArrayWriter использует массив для выходного потока.

Класс FileWriter

Класс FileWriter создаёт объект класса, производного от класса Writer, который вы можете применять для записи файла. Есть конструкторы, которые позволяют добавить вывод в конец файла. Создание объекта не зависит от наличия файла, он будет создан в случае необходимости. Если файл существует и он доступен только для чтения, то передаётся исключение IOException.

Чтение и запись файлов

В filename нужно указать имя файла, который вы хотите открыть. Если при создании входного потока файл не существует, передаётся исключение FileNotFoundException. Аналогично для выходных потоков, если файл не может быть открыт или создан, также передаётся исключение. Сам класс исключения происходит от класса IOException. Когда выходной файл открыт, любой ранее существовавший файл с тем же именем уничтожается.

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

В JDK 7 метод close() определяется интерфейсом AutoCloseable и можно явно не закрывать файл, а использовать новый оператор try-с-ресурсами, что для Android пока не слишком актуально.

Иногда используют вариант, когда метод close() помещается в блок finally. При таком подходе все методы, которые получают доступ к файлу, содержатся в пределах блока try, а блок finally используется для закрытия файла. Таким образом, независимо от того, как закончится блок try, файл будет закрыт.

Так как исключение FileNotFoundException является подклассом IOException, то не обязательно обрабатывать два исключения отдельно, а оставить только IOException, если вам не нужно отдельно обрабатывать разные причины неудачного открытия файла. Например, если пользователь вводит вручную имя файла, то более конкретное исключение будет к месту.

Для записи в файл используется метод write().

Метод пишет в файл байт, переданный параметром value. Хотя параметр объявлена как целочисленный, в файл записываются только младшие восемь бит. При ошибке записи передаётся исключение.

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

Когда в Android будет полноценная поддержка JDK 7, то дополним материал.

Чтобы открыть файл для посимвольного чтения, используется класс FileInputReader; имя файла задаётся в виде строки (String) или объекта File. Ускорить процесс чтения помогает буферизация ввода, для этого полученная ссылка передаётся в конструктор класса BufferedReader. Так как в интерфейсе класса имеется метод readLine(), все необходимое для чтения имеется в вашем распоряжении. При достижении конца файла метод readLine() возвращает ссылку null.

Объект FileWriter записывает данные в файл. При вводе/выводе практически всегда применяется буферизация, поэтому используется BufferedWriter.

Когда данные входного потока исчерпываются, метод readLine() возвращает null. Для потока явно вызывается метод close(); если не вызвать его для всех выходных файловых потоков, в буферах могут остаться данные, и файл получится неполным.

PrintWriter форматирует данные так, чтобы их мог прочитать человек. Однако для вывода информации, предназначенной для другого потока, следует использовать классы DataOutputStream для записи данных и DataInputStream для чтения данных.

Единственным надежным способом записать в поток DataOutputStream строку так, чтобы ее можно было потом правильно считать потоком DataInputStream, является кодирование UTF-8, реализуемое методами readUTF() и writeUTF(). Эти методы позволяют смешивать строки и другие типы данных, записываемые потоком DataOutputStream, так как вы знаете, что строки будут правильно сохранены в Юникоде и их будет просто воспроизвести потоком DataInputStream.

Метод writeDouble() записывает число double в поток, а соответствующий ему метод readDouble() затем восстанавливает его (для других типов также существуют подобные методы).

Работа с классом RandomAccessFile напоминает использование совмещенных в одном классе потоков DataInputStream и DataOutputStream (они реализуют те же интерфейсы DataInput и DataOutput). Кроме того, метод seek() позволяет переместиться к определенной позиции и изменить хранящееся там значение.

Читайте также:  с какими странами торгует россия

При использовании RandomAccessFile необходимо знать структуру файла. Класс RandomAccessFile содержит методы для чтения и записи примитивов и строк UTF-8.

RandomAccessFile может открываться в режиме чтения («r») или чтения/записи («rw»). Также есть режим «rws», когда файл открывается для операций чтения-записи и каждое изменение данных файла немедленно записывается на физическое устройство.

Исключения ввода/вывода

В большинстве случаев у классов ввода/вывода используется исключение IOException. Второе исключение FileNotFoundException передаётся в тех случаях, когад файл не может быть открыт. Данное исключение происходит от IOException, поэтому оба исключения можно обрабатывать в одном блоке catch, если у вас нет нужды обрабатывать их по отдельности.

Источник

Как работает Flush в Hibernate

В этой статье рассмотрим, что делает метод flush(), и когда он вызывается неявно.

Что такое flush()

Этот метод есть как у JPA EntityManager:

так и у Hibernate Session:

Он транслирует изменения отслеживаемых сущностей в базу данных, то есть выполняет накопившиеся SQL-команды.

Режим FlushMode.AUTO

Дело в том, что когда мы переводим JPA сущности из одного состояния в другое, то есть вызываем для них методы сохранения, удаления (persist(), merge(), remove()), немедленного выполнения SQL-команд не происходит. SQL-команды накапливаются, а выполнение их откладывается на потом, до необходимого момента, а именно:

С п.1 все ясно — в конце транзакции изменения всё же должны попасть в базу данных.

Что касается п. 2 и 3 — если перед select не сбросить изменения в базу, то select их не увидит, поэтому 2 и 3 тоже считаются необходимыми моментами. Транзакция должна видеть изменения, сделанные в ней самой.

Именно так работает автоматический режим сброса изменений в базу FlushMode.AUTO. Специально его устанавливать не надо, он и так стоит.

Но иногда все-таки нужно сбросить изменения в базу вручную методом flush().

Пример использования flush()

Дело в том, что автоматически изменения сбрасываются в базу еще и в определенном порядке, и persist() выполняется перед remove().

Рассмотрим пример. Пусть у нас есть класс City с уникальным названием:

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

Благодаря em.flush() после em.remove() удается сразу протолкнуть в базу удаление, до того, как будет выполнена попытка повторного persist(). И избежать исключения.

Код выше приведен только для демонстрации смысла flush().

Еще раз, без flush() операции выполняются (точнее, пытаются выполниться) в конце транзакции в таком порядке, что вызывает исключение:

До delete не доходит, нарушение уникальности вызывает второй insert.

А такой порядок операций с flush():

Тут методом flush() мы принудительно вызываем сброс накопившихся изменений (первый persist() и remove()) в базу, так что remove() проходит.

Порядок сброса операций в базу

Вообще при сбросе изменений в базу операции выполняются в таком порядке:

Удаление (EntityDeleteAction) идет в самом конце, что и случается в предыдущем примере.

Источник

Потоки ввода-вывода. Работа с файлами

Потоки ввода-вывода

Поток связан с реальным физическим устройством с помощью системы ввода-вывода Java. У нас может быть определен поток, который связан с файлом и через который мы можем вести чтение или запись файла. Это также может быть поток, связанный с сетевым сокетом, с помощью которого можно получить или отправить данные в сети. Все эти задачи: чтение и запись различных файлов, обмен информацией по сети, ввод-ввывод в консоли мы будем решать в Java с помощью потоков.

В основе всех классов, управляющих потоками байтов, находятся два абстрактных класса: InputStream (представляющий потоки ввода) и OutputStream (представляющий потоки вывода)

Но поскольку работать с байтами не очень удобно, то для работы с потоками символов были добавлены абстрактные классы Reader (для чтения потоков символов) и Writer (для записи потоков символов).

Читайте также:  Что значит таможенная очистка товара

Все остальные классы, работающие с потоками, являются наследниками этих абстрактных классов. Основные классы потоков:

Потоки байтов

Класс InputStream

Класс InputStream является базовым для всех классов, управляющих байтовыми потоками ввода. Рассмотрим его основные методы:

int available() : возвращает количество байтов, доступных для чтения в потоке

void close() : закрывает поток

long skip(long number) : пропускает в потоке при чтении некоторое количество байт, которое равно number

Класс OutputStream

Класс OutputStream является базовым классом для всех классов, которые работают с бинарными потоками записи. Свою функциональность он реализует через следующие методы:

void close() : закрывает поток

void flush() : очищает буфер вывода, записывая все его содержимое

void write(int b) : записывает в выходной поток один байт, который представлен целочисленным параметром b

void write(byte[] buffer) : записывает в выходной поток массив байтов buffer.

Абстрактные классы Reader и Writer

Абстрактный класс Reader предоставляет функционал для чтения текстовой информации. Рассмотрим его основные методы:

absract void close() : закрывает поток ввода

absract int read(char[] buffer, int offset, int count) : считывает в массив buffer, начиная со смещения offset, из потока символы, количество которых равно count

long skip(long count) : пропускает количество символов, равное count. Возвращает число успешно пропущенных символов

Класс Writer определяет функционал для всех символьных потоков вывода. Его основные методы:

Writer append(char c) : добавляет в конец выходного потока символ c. Возвращает объект Writer

Writer append(CharSequence chars) : добавляет в конец выходного потока набор символов chars. Возвращает объект Writer

abstract void close() : закрывает поток

abstract void flush() : очищает буферы потока

void write(int c) : записывает в поток один символ, который имеет целочисленное представление

void write(char[] buffer) : записывает в поток массив символов

absract void write(char[] buffer, int off, int len) : записывает в поток только несколько символов из массива buffer. Причем количество символов равно len, а отбор символов из массива начинается с индекса off

void write(String str) : записывает в поток строку

void write(String str, int off, int len) : записывает в поток из строки некоторое количество символов, которое равно len, причем отбор символов из строки начинается с индекса off

Функционал, описанный классами Reader и Writer, наследуется непосредственно классами символьных потоков, в частности классами FileReader и FileWriter соответственно, предназначенными для работы с текстовыми файлами.

Теперь рассмотрим конкретные классы потоков.

Источник

Какова цель flush () в потоках Java?

Подскажите несколько предложений.

7 ответов

Из документации из flush метод:

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

Если буфер заполнен, все строки, которые буферизированы в нем, будут сохранены на диск. Буферы используются, чтобы избежать больших сделок! и накладные расходы.

В классе BufferedWriter, который помещается в java libs, есть одна строка вроде:

Если вы хотите отправить данные до того, как буфер заполнится, у вас есть контроль. Просто промойте это. Вызовы writer.flush () говорят: «Отправьте все, что есть в буфере, сейчас же!

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

Из-за проблем с производительностью первые данные должны быть записаны в буфер. Когда буфер заполняется, данные записываются в вывод (файл, консоль и т. Д.). Когда буфер частично заполнен и вы хотите отправить его на вывод (файл, консоль), вам необходимо вызвать метод flush () вручную, чтобы записать частично заполненный буфер на вывод (файл, консоль).

В дополнение к другим хорошим ответам здесь это объяснение прояснило для меня все:

Источник

Сказочный портал