Разница в io при работе с файлом и директорией
Класс File пакета java.io используется для управления информацией о файлах и каталогах. На уровне операционной системы файлы и каталоги имеют существенные отличия, но в Java они описываются одним классом File. Каталог в Java трактуется как обычный файл, но с дополнительным свойством — списком имен файлов, который можно просмотреть с помощью метода list.
В зависимости от назначения объект File - файл или каталог, можно использовать один из конструкторов для создания объекта:
Примеры создания объектов File
Интерфейс FileFilter
Класс File включает метод, позволяющий прочитать список только определенных файлов.
В отличие от одноименного метода, но без параметра, данный метод отбирает только те файлы каталога, которые удовлетворяют определенному условию. Параметр filter предназначен для задания этого условия. При этом тип параметра FileFilter — это не класс, а интерфейс, который имеет всего один метод, возвращающий true, если файл удовлетворяет определенным условиям, и false в противном случае.
Метод listFiles будет вызывать метод accept для каждого файла в каталоге, и те, для которых accept вернет true, будут включены в результирующий список. Остальные будут проигнорированы.
Для использования FileFilter необходимо создать объект и определить в нем соответствующий метод accept.
Пример использования фильтра FileFilter
Пример
В следующем примере представлены InputStream и OutputStream – потоки для чтения, создания и записи файла:
Представленный выше java-код создаст файл file.txt и пропишет заданные символы в формате char. То же самое будет выводиться на экран стандартного вывода.
Поток FileInputStream – чтение из файла
Поток FileInputStream – это поток, который используется в Java для чтения данных из файла. Объекты могут быть созданы при использовании ключевого слова new, доступны несколько типов конструкторов.
Представленный конструктор использует имя файла в качестве потока с целью создания объекта входного потока для считывания файла:
Представленный ниже конструктор использует объектный файл с целью создания объекта входного потока для чтения файла. Сперва мы создаем объектный файл при использовании метода File() следующим образом:
Теперь, получив объект InputStream, следует ознакомиться со следующим перечнем вспомогательных методов, которые могут быть использованы для считывания потока либо выполнения иных операций в потоке.
№ | Метод и описание |
1 | public void close() throws IOException<> Данный метод в Java закрывает выходной файловый поток. Освобождает какие-либо системные ресурсы, связанные с файлом. Выдает IOException. |
2 | protected void finalize()throws IOException <> Данный метод выполняет очистку соединения с файлом. Позволяет удостовериться в вызове закрытого метода данного выходного файлового потока при отсутствии каких-либо ссылок на данный поток. Выдает IOException. |
3 | public int read(int r)throws IOException<> Данный метод осуществляет в Java считывание заданных байтов данных из InputStream. Возврат данных типа int. Возврат следующего байта данных, в конце файла будет произведен возврат к -1. |
4 | public int read(byte[] r) throws IOException<> Данный метод производит считывание байтов r.length из входного потока в массив. Возврат общего числа считанных байтов. В конце файла будет произведен возврат к -1. |
5 | public int available() throws IOException<> Выдает число байтов, которые могут быть считаны из входного файлового потока. Возврат данных типа int. |
Существуют также другие доступные входные потоки, более детальные сведения о которых представлены по следующим ссылкам:
Пример
Вследствие этого будет получен следующий результат, основанный на каталогах и файлах, доступных в вашем каталоге /NetBeans 8.2/Projects/ReadDirectory/ReadDirectory/:
Что бы программы ни делали, рано или поздно у большинства из них возникает задача сохранить результаты своей деятельности. В самом простом случае в роли такого хранилища выступает файловая система.
Популярность Java на старте не в последнюю очередь была обусловлена тем, что Java содержала развитые средства для работы с файловой системой и потоками байтов. Эти средства называют системой ввода-вывода - или Java IO (Input & Output). Если вы в полной мере овладеете Java IO, то будете не единожды чувствовать себя в роли пресловутого Ослика ИА, наблюдая, как замечательно входят и выходят потоки данных в и из вашей программы=)
Классы системы ввода-вывода находятся в пакете java.io, и первый взгляд на них ужасает - около 90 классов, некоторые из которых понять не представляется возможным - такое оттолкнет даже самые пытливые умы. Но не следует пугаться, на самом деле Java IO базируется на довольно простых концепциях, о которых я сейчас вам расскажу.
Во-первых, нужно твердо уяснить, что файловая система, файлы, директории - все это в разных операционных системах устроено очень по-разному. Но поскольку Java - кроссплатформенный язык, то работать с различными файловыми системами она должна одинаково. Поэтому файловая система в представлении Java - это некая абстракция, позволяющая работать с теми свойствами, которые реализованы практически во всех широко распространенных файловых системах.
Базовая сущность файловой системы - это файл. Операции с файлами делятся на 2 большие группы: те, которые работают с содержимым файла (чтение, запись и т.п.), и те, которые не затрагивают содержимое файлов (переименование, удаление, перемещение и т.п.).
Итак, базовая сущность файловой системы - это файл. Для работы с этой сущностью существует класс java.io.File. Этот класс представляет собой как простые файлы, так и директории (папки).
Допустим, у нас есть папка "C:/temp" и мы хотим работать с файлом 1.bin в этой папке. Чтобы это сделать - нужно сначала создать объект класса File. Отмечу, что создание объекта класса File не создает файл непосредственно в файловой системе, речь идет лишь об объекте в памяти. Напишем простую программу, которая демонстрирует как прочитать основные свойства файла:
Удаление файлов происходит довольно тривиально - вызовом метода delete() класса File. Следует помнить, что для успешного удаления папки, необходимо предварительно удалить ее содержимое. В общем случае удаление папки происходит так:
Ну что ж, дорогой читатель, на этом я завершу вводную статью в Java IO. Мы научились создавать файлы и папки удалять, читать их свойства и осуществлять навигацию по файловой системе.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Потоки ввода/вывода в Java
В чём заключается разница между IO и NIO?
- Java IO (input-output) является потокоориентированным, а Java NIO (new/non-blocking io) – буфер-ориентированным. Потокоориентированный ввод/вывод подразумевает чтение/запись из потока/в поток одного или нескольких байт в единицу времени поочередно. Данная информация нигде не кэшируются. Таким образом, невозможно произвольно двигаться по потоку данных вперед или назад. В Java NIO данные сначала считываются в буфер, что дает больше гибкости при обработке данных.
- Потоки ввода/вывода в Java IO являются блокирующими. Это значит, что когда в потоке выполнения вызывается read() или write() метод любого класса из пакета java.io.* , происходит блокировка до тех пор, пока данные не будут считаны или записаны. Поток выполнения в данный момент не может делать ничего другого. Неблокирующий режим Java NIO позволяет запрашивать считанные данные из канала (channel) и получать только то, что доступно на данный момент, или вообще ничего, если доступных данных пока нет. Вместо того, чтобы оставаться заблокированным пока данные не станут доступными для считывания, поток выполнения может заняться чем-то другим. Тоже самое справедливо и для неблокирующего вывода. Поток выполнения может запросить запись в канал некоторых данных, но не дожидаться при этом пока они не будут полностью записаны.
- В Java NIO имеются селекторы, которые позволяют одному потоку выполнения мониторить несколько каналов ввода. Т.е. существует возможность зарегистрировать несколько каналов с селектором, а потом использовать один поток выполнения для обслуживания каналов, имеющих доступные для обработки данные, или для выбора каналов, готовых для записи.
Какие особенности NIO вы знаете?
- Каналы и селекторы: NIO поддерживает различные типы каналов. Канал является абстракцией объектов более низкого уровня файловой системы (например, отображенные в памяти файлы и блокировки файлов), что позволяет передавать данные с более высокой скоростью. Каналы не блокируются и поэтому Java предоставляет еще такие инструменты, как селектор, который позволяет выбрать готовый канал для передачи данных, и сокет, который является инструментом для блокировки.
- Буферы: имеет буферизация для всех классов-обёрток примитивов (кроме Boolean). Появился абстрактный класс Buffer, который предоставляет такие операции, как clear, flip, mark и т.д. Его подклассы предоставляют методы для получения и установки данных.
- Кодировки: появились кодеры и декодеры для отображения байт и символов Unicode. к оглавлению
Каналы напоминают трубопроводы, по которым эффективно транспортируются данные между буферами байтов и сущностями по ту сторону каналов. Каналы – это шлюзы, которые позволяют получить доступ к сервисам ввода/вывода операционной системы с минимальными накладными расходами, а буферы – внутренние конечные точки этих шлюзов, используемые для передачи и приема данных.
Какие существуют виды потоков ввода/вывода?
Назовите основные классы потоков ввода/вывода.
Разделяют два вида потоков ввода/вывода:
- байтовые - java.io.InputStream , java.io.OutputStream ;
- символьные - java.io.Reader , java.io.Writer .
В каких пакетах расположены классы потоков ввода/вывода?
java.io , java.nio . Для работы с потоками компрессированных данных используются классы из пакета java.util.zip
Какие подклассы класса InputStream вы знаете, для чего они предназначены?
- InputStream - абстрактный класс, описывающий поток ввода;
- BufferedInputStream - буферизованный входной поток;
- ByteArrayInputStream позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока;
- DataInputStream - входной поток для байтовых данных, включающий методы для чтения стандартных типов данных Java;
- FileInputStream - входной поток для чтения информации из файла;
- FilterInputStream - абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства;
- ObjectInputStream - входной поток для объектов;
- StringBufferInputStream превращает строку ( String ) во входной поток данных InputStream ;
- PipedInputStream реализует понятие входного канала;
- PushbackInputStream - разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток, позволяет «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий момент, не извлекая информации.
- SequenceInputStream используется для слияния двух или более потоков InputStream в единый.
Для чего используется PushbackInputStream ?
Разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток. Класс PushbackInputStream представляет механизм «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий момент, не извлекая информации.
У класса есть дополнительный метод unread().
Для чего используется SequenceInputStream ?
Класс SequenceInputStream позволяет сливать вместе несколько экземпляров класса InputStream . Конструктор принимает в качестве аргумента либо пару объектов класса InputStream , либо интерфейс Enumeration .
Во время работы класс выполняет запросы на чтение из первого объекта класса InputStream и до конца, а затем переключается на второй. При использовании интерфейса работа продолжится по всем объектам класса InputStream . По достижении конца, связанный с ним поток закрывается. Закрытие потока, созданного объектом класса SequenceInputStream , приводит к закрытию всех открытых потоков.
Какой класс позволяет читать данные из входного байтового потока в формате примитивных типов данных?
Класс DataInputStream представляет поток ввода и предназначен для записи данных примитивных типов, таких, как int , double и т.д. Для каждого примитивного типа определен свой метод для считывания:
Какие подклассы класса OutputStream вы знаете, для чего они предназначены?
- OutputStream - это абстрактный класс, определяющий потоковый байтовый вывод;
- BufferedOutputStream - буферизированный выходной поток;
- ByteArrayOutputStream - все данные, посылаемые в этот поток, размещаются в предварительно созданном буфере;
- DataOutputStream - выходной поток байт, включающий методы для записи стандартных типов данных Java;
- FileOutputStream - запись данных в файл на физическом носителе;
- FilterOutputStream - абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства;
- PrintStream - выходной поток, включающий методы print() и println() ;
- ObjectOutputStream - выходной поток для записи объектов;
- PipedOutputStream реализует понятие выходного канала.
Какие подклассы класса Reader вы знаете, для чего они предназначены?
- Reader - абстрактный класс, описывающий символьный ввод;
- BufferedReader - буферизованный входной символьный поток;
- CharArrayReader - входной поток, который читает из символьного массива;
- FileReader - входной поток, читающий файл;
- FilterReader - абстрактный класс, предоставляющий интерфейс для классов-надстроек;
- InputStreamReader - входной поток, транслирующий байты в символы;
- LineNumberReader - входной поток, подсчитывающий строки;
- PipedReader - входной канал;
- PushbackReader - входной поток, позволяющий возвращать символы обратно в поток;
- StringReader - входной поток, читающий из строки.
Какие подклассы класса Writer вы знаете, для чего они предназначены?
- Writer - абстрактный класс, описывающий символьный вывод;
- BufferedWriter - буферизованный выходной символьный поток;
- CharArrayWriter - выходной поток, который пишет в символьный массив;
- FileWriter - выходной поток, пишущий в файл;
- FilterWriter - абстрактный класс, предоставляющий интерфейс для классов-надстроек;
- OutputStreamWriter - выходной поток, транслирующий байты в символы;
- PipedWriter - выходной канал;
- PrintWriter - выходной поток символов, включающий методы print() и println() ;
- StringWriter - выходной поток, пишущий в строку;
В чем отличие класса PrintWriter от PrintStream ?
Прежде всего, в классе PrintWriter применен усовершенствованный способ работы с символами Unicode и другой механизм буферизации вывода: в классе PrintStream буфер вывода сбрасывался всякий раз, когда вызывался метод print() или println() , а при использовании класса PrintWriter существует возможность отказаться от автоматического сброса буферов, выполняя его явным образом при помощи метода flush() .
Кроме того, методы класса PrintWriter никогда не создают исключений. Для проверки ошибок необходимо явно вызвать метод checkError() .
Чем отличаются и что общего у InputStream , OutputStream , Reader , Writer ?
- InputStream и его наследники - совокупность для получения байтовых данных из различных источников;
- OutputStream и его наследники - набор классов, определяющих потоковый байтовый вывод;
- Reader и его наследники определяют потоковый ввод символов Unicode;
- Writer и его наследники определяют потоковый вывод символов Unicode.
Какие классы позволяют преобразовать байтовые потоки в символьные и обратно?
- OutputStreamWriter — «мост» между классом OutputStream и классом Writer . Символы, записанные в поток, преобразовываются в байты.
- InputStreamReader — аналог для чтения. При помощи методов класса Reader читаются байты из потока InputStream и далее преобразуются в символы.
Какие классы позволяют ускорить чтение/запись за счет использования буфера?
- BufferedInputStream(InputStream in) / BufferedInputStream(InputStream in, int size) ,
- BufferedOutputStream(OutputStream out) / BufferedOutputStream(OutputStream out, int size) ,
- BufferedReader(Reader r) / BufferedReader(Reader in, int sz) ,
- BufferedWriter(Writer out) / BufferedWriter(Writer out, int sz)
Какой класс предназначен для работы с элементами файловой системы?
File работает непосредственно с файлами и каталогами. Данный класс позволяет создавать новые элементы и получать информацию существующих: размер, права доступа, время и дату создания, путь к родительскому каталогу.
Какие методы класса File вы знаете?
Наиболее используемые методы класса File :
- boolean createNewFile() : делает попытку создать новый файл;
- boolean delete() : делает попытку удалить каталог или файл;
- boolean mkdir() : делает попытку создать новый каталог;
- boolean renameTo(File dest) : делает попытку переименовать файл или каталог;
- boolean exists() : проверяет, существует ли файл или каталог;
- String getAbsolutePath() : возвращает абсолютный путь для пути, переданного в конструктор объекта;
- String getName() : возвращает краткое имя файла или каталога;
- String getParent() : возвращает имя родительского каталога;
- boolean isDirectory() : возвращает значение true , если по указанному пути располагается каталог;
- boolean isFile() : возвращает значение true , если по указанному пути находится файл;
- boolean isHidden() : возвращает значение true , если каталог или файл являются скрытыми;
- long length() : возвращает размер файла в байтах;
- long lastModified() : возвращает время последнего изменения файла или каталога;
- String[] list() : возвращает массив файлов и подкаталогов, которые находятся в определенном каталоге;
- File[] listFiles() : возвращает массив файлов и подкаталогов, которые находятся в определенном каталоге.
Что вы знаете об интерфейсе FileFilter ?
Интерфейс FileFilter применяется для проверки, попадает ли объект File под некоторое условие. Этот интерфейс содержит единственный метод boolean accept(File pathName) . Этот метод необходимо переопределить и реализовать. Например:
Как выбрать все элементы определенного каталога по критерию (например, с определенным расширением)?
Метод File.listFiles() возвращает массив объектов File , содержащихся в каталоге. Метод может принимать в качестве параметра объект класса, реализующего FileFilter . Это позволяет включить в список только те элементы, для которых метод accept возвращает true (критерием может быть длина имени файла или его расширение).
Что вы знаете о RandomAccessFile ?
Класс java.io.RandomAccessFile обеспечивает чтение и запись данных в произвольном месте файла. Он не является частью иерархии InputStream или OutputStream . Это полностью отдельный класс, имеющий свои собственные (в большинстве своем native) методы. Объяснением этого может быть то, что RandomAccessFile имеет во многом отличающееся поведение по сравнению с остальными классами ввода/вывода так как позволяет, в пределах файла, перемещаться вперед и назад.
RandomAccessFile имеет такие специфические методы как:
- getFilePointer() для определения текущего местоположения в файле;
- seek() для перемещения на новую позицию в файле;
- length() для выяснения размера файла;
- setLength() для установки размера файла;
- skipBytes() для того, чтобы попытаться пропустить определённое число байт;
- getChannel() для работы с уникальным файловым каналом, ассоциированным с заданным файлом;
- методы для выполнения обычного и форматированного вывода из файла ( read() , readInt() , readLine() , readUTF() и т.п.);
- методы для обычной или форматированной записи в файл с прямым доступом ( write() , writeBoolean() , writeByte() и т.п.).
Так же следует отметить, что конструкторы RandomAccessFile требуют второй аргумент, указывающий необходимый режим доступа к файлу - только чтение ( "r" ), чтение и запись ( "rw" ) или иную их разновидность.
Какие режимы доступа к файлу есть у RandomAccessFile ?
- "r" открывает файл только для чтения. Запуск любых методов записи данных приведет к выбросу исключения IOException .
- "rw" открывает файл для чтения и записи. Если файл еще не создан, то осуществляется попытка создать его.
- "rws" открывает файл для чтения и записи подобно "rw" , но требует от системы при каждом изменении содержимого файла или метаданных синхронно записывать эти изменения на физический носитель.
- "rwd" открывает файл для чтения и записи подобно "rws" , но требует от системы синхронно записывать изменения на физический носитель только при каждом изменении содержимого файла. Если изменяются метаданные, синхронная запись не требуется.
Какие классы поддерживают чтение и запись потоков в компрессированном формате?
- DeflaterOutputStream - компрессия данных в формате deflate.
- Deflater - компрессия данных в формат ZLIB
- ZipOutputStream - потомок DeflaterOutputStream для компрессии данных в формат Zip.
- GZIPOutputStream - потомок DeflaterOutputStream для компрессии данных в формат GZIP.
- InflaterInputStream - декомпрессия данных в формате deflate.
- Inflater - декомпрессия данных в формате ZLIB
- ZipInputStream - потомок InflaterInputStream для декомпрессии данных в формате Zip.
- GZIPInputStream - потомок InflaterInputStream для декомпрессии данных в формате GZIP.
Класс System позволяет вам перенаправлять стандартный ввод, вывод и поток вывода ошибок, используя простой вызов статического метода:
- setIn(InputStream) - для ввода;
- setOut(PrintStream) - для вывода;
- setErr(PrintStream) - для вывода ошибок.
Какой символ является разделителем при указании пути в файловой системе?
Для различных операционных систем символ разделителя различается. Для Windows это \ , для Linux - / .
В Java получить разделитель для текущей операционной системы можно через обращение к статическому полю File.separator .
Что такое «абсолютный путь» и «относительный путь»?
Абсолютный (полный) путь — это путь, который указывает на одно и то же место в файловой системе, вне зависимости от текущей рабочей директории или других обстоятельств. Полный путь всегда начинается с корневого каталога.
Относительный путь представляет собой путь по отношению к текущему рабочему каталогу пользователя или активного приложения.
Что такое «символьная ссылка»?
Символьные ссылки используются для более удобной организации структуры файлов на компьютере, так как:
Если какой-либо член класса не поддерживает клонирование, то в методе клонирования необходимо создать новый экземпляр этого класса и скопировать каждый его член со всеми атрибутами в новый объект класса, по одному. Каждый класс в иерархии должен обязательно иметь свой переопределенный clone(), тогда большинство проблем можно решить просто используя super.clone().
Еще один вариант клонирования объекта - это конструктор копирования . Создается конструктор, принимающий на вход объект того же класса, который необходимо клонировать:
Object. clone () поумолчанию выполняет поверхностную копию .
Экземпляры класса java.io.BufferedReader предназначены для чтения потока символов с буферизацией (символов, массивов и строк).
Использовать метод File.createNewFile(). Этот метод возвращает логическое значение
Если вы хотите создать новый файл и в то же время, если хотите записать в него некоторые данные, вы можете использовать метод записи FileOutputStream. В Java FileOutputStream является классом потока байтов. Чтобы записать данные в файл, вы должны преобразовать данные в байты, а затем сохранить их в файл.
Создание временного файла в java может потребоваться во многих сценариях, но в основном это происходит во время модульных тестов, где вы не хотите сохранять результаты. Создание с помощью java.io.File.createTempFile()
Полный илиабсолютный путь— это путь, который указывает на одно и то же место в файловой системе, вне зависимости от текущего рабочего каталога или других обстоятельств. Полный путь всегда начинается с корневого каталога. Относительный путьпредставляет собой путь по отношению к текущему рабочему каталогу пользователя или активных приложений.
Интерфейс Externalizable - это интерфейс, который позволяет вам определять пользовательские правила и собственный механизм для сериализации. Сериализация по умолчанию не защищает конфиденциальную информацию, такую как пароли и учетные данные, или что, если разработчики хотят обеспечить некоторую информацию во время процесса сериализации?
Если мы изменим структуру нашего класса, например поля удаления / добавления, этот номер версии serialVersionUID также изменится, и в соответствии с JVM наш класс не будет совместим с версией класса сериализованного объекта. Вот почему мы получаем исключение InvalidClassException . JVMпросто напросто не понимает как десериализовать сериализованный класс!
BufferedReader/BufferedWriter - наследник Reader/Writer добавляющий методы чтения и записи целых строк , а не отдельных символов. буферизуя прочитанные символы, чтобы обеспечить эффективное считывание символов, массивов и строк. Можно указать в конструкторе вторым параметром размер буфера.
Потоки – можно не закрывать, но затем, когда код из самостоятельной единицы превращается в часть кода другой, более мощной программы. Но Ваш код не освобождает ресурсы и в результате эти ресурсы "висят" невостребованными. Более того, Ваш код выполняется много раз и каждый раз открывает ресурс и не закрывает его. Такое поведение по меньшей мере приводит к напрасному расходу этих ресурсов, а в более глобальной перспективе замедляет работу не только программы, но и компьютера, на котором она выполняется.
Path , по большому счету, — это переработанный аналог класса File . Работать с ним значительно проще , чем с File.
Во-вторых, в Path были упорядочены возвращаемые значения методов. В классе File методы возвращали то String, то boolean, то File — разобраться было непросто.
Например, был метод getParent(), который возвращал родительский путь для текущего файла в виде строки. Но при этом был метод getParentFile(), который возвращал то же самое, но в виде объекта File!
Это явно избыточно. Поэтому в интерфейсе Path метод getParent() и другие методы работы с файлами возвращают просто объект Path. Никакой кучи вариантов — все легко и просто.
Files(относится к NIO )
Files — это утилитный класс, куда были вынесены статические методы из класса File. Files — это примерно то же, что и Arrays или Collections, только работает он с файлами, а не с массивами и коллекциями :)
Он сосредоточен на управлении файлами и директориями. Используя статические методы Files, мы можем создавать, удалять и перемещать файлы и директории.
Поля с модификатором final сериализуются как и обычные . За одним исключением – их невозможно десериализовать при использовании Externalizable , поскольку final-поля должны быть инициализированы в конструкторе, а после этого в readExternal изменить значение этого поля будет невозможно. Соответственно, если необходимо сериализовать объект с final-полем неоходимо использовать только стандартную сериализацию.
В классе Thread определены семь перегруженных конструкторов, большое количество методов, предназначенных для работы с потоками, и три константы (приоритеты выполнения потока).
Не нужно закрывать обычный StreamизStreamAPI.
Строки – неизменяемый объект, мы можем копировать их просто ссылаясь на них.
Так как строки иммутабельны, клонировать их не обязательно (хотя можно). Хватит и клонировать только массив, а строки использовать те же
При стандартной сериализации поля, имеющие модификатор static, не сериализуются. Соответственно, после десериализации это поле значения не меняет. При использовании реализации Externalizable сериализовать и десериализовать статическое поле можно, но не рекомендуется этого делать, т.к. это может сопровождаться трудноуловимыми ошибками. Поле с модификатором trainsent, будет равно null.
flush (), очищает все потоки данных и полностью их записывает, а также дает новое пространство для новых потоков во временном расположении буфера. Но если буффер пустой (/ не попали данные черезwrite) – то ничего записано не будет
Токен (или маркер) представляет собой серию цифровых или буквенно-цифровых символов, которая заканчивается разделителем. Разделителем может быть символ табуляции, возврат каретки (перевод строки или же просто ‘Enter’), конец файла или пробел.
Переопределение метода clone() и реализация интерфейса Cloneable(); Использование конструктора копирования;
Использовать для клонирования механизм сериализации.
System.out/System.in – консольные потоки ввода вывода.
Cканнер очень сильно проигрывает по быстродействию, он примерно в 1000 раз медленнее, чем BufferedReader. Но у сканнера уже впилены удобные функции по разбору текста на разные данные (целые числа, дробные числа, текст и тп), когда у bufferedreader-a их придется отдельно парсить.
Класс File, определенный в пакете java.io, не работает напрямую с потоками. Его задачей является управление информацией о файлах и каталогах. Хотя на уровне операционной системы файлы и каталоги отличаются, но в Java они описываются одним классом File.
File(String путь_к_каталогу)
File(String путь_к_каталогу, String имя_файла)
File(File каталог, String имя_файла)
Способы создания:
Использовать метод File.createNewFile(). Этот метод возвращает логическое значение
Если вы хотите создать новый файл и в то же время, если хотите записать в него некоторые данные, вы можете использовать метод записи FileOutputStream. В Java FileOutputStream является классом потока байтов. Чтобы записать данные в файл, вы должны преобразовать данные в байты, а затем сохранить их в файл.
Создание временного файла в java может потребоваться во многих сценариях, но в основном это происходит во время модульных тестов, где вы не хотите сохранять результаты. Создание с помощью java.io.File.createTempFile()
Java не может удалять папки с данными в нем. Вы должны удалить все файлы перед удалением папки.
for(String s: entries)
File currentFile = new File(index.getPath(),s);
currentFile.delete();
Он возвращает int, потому что, когда поток больше не может быть прочитан, он возвращает -1.
255, так как обрезается до 8 битов
System.out.println(Arrays.toString(bytes));
В переводе на русский означает, что flush() вызывает чистку буфера вызывая метод реализованный в самой ОС поверх которой работает JVM. При этом даже отсутствие буфера в самом потоке не означает, что не будет использоваться в качестве буфера кэш диска на уровне ОСи или даже ниже. Использование flush() – хороший тон поскольку, девелопер не знает есть ли буфер на уровне ОС
Декоратор — это структурный паттерн, который позволяет добавлять объектам новые поведения на лету, помещая их в объекты-обёртки. inputstream, bytearrayinputstream, stringbuilderinputstreams и так далее являются основанными элементами . Filterinputstream - это базовый класс для классов декораторов. Фильтр входных потоков (например, bufferedinput stream) может выполнять дополнительные функции при чтении потоков или записи в них. Он реализует все те же методы, что и I nputStream , который лежит в нём, но позволяет к ним добавить доп. функционал . Конкретно его используют для какой-либо модификации данных из InputStream (т.е. фильтрации).
OutputStreamWriter мы легко «адаптирует» два интерфейса классов Writer и OutputStream друг другу.
Клонирование – создает что-то новое на основе существующего.
Если вы хотите, чтобы буфер был сброшен, да, вызовите flush() перед вызовом close() .
Java IO (input-output) является потокоориентированным
Java NIO (new/non-blocking io) – буфер-ориентированным.
Static (если не сделали нужный static метод) и transient
Когда Serializable класс имеет цепочку родителей, пока эти родители тоже Serializable, десериализация объекта идет от родителя к наследнику, в обход конструктора.Вместо него вызываются методы readObject (readObjectNoData). Но как только встречается первый предок, не реализующий интерфейс Serializable, инициализация для него возвращается в нормальное русло – вместо readObject вызывается конструктор без аргументов. Если такого конструктора нет, или он объявлен private, исполнение выбросит InvalidClassException.
Соответственно, если необходимо сериализовать объект с final полем необходимо использовать только стандартную сериализацию. Так как их невозможно десериализовать при использовании Externalizable, поскольку final поля должны быть инициализированы в конструкторе, а после этого в readExternal() изменить значение этого поля будет невозможно.
При записи Serializable класса весь контроль над сериализацией достается JVM. С помощью определения специальных методов можно кастомизировать его части. Метод readObject при этом обычно начинается с вызова стандартной части сериализации – ObjectInputStream.defaultReadObject().
Этот интерфейс позволяет реализовать полностью свой механизм сериализации, стандартно запишется только идентификатор класса. Никакой автоматической работы с классом-родителем также не предусмотрено. Методы readObject и writeObject игнорируются. Ключевое слово transient эффекта на Externalizable не имеет.
Метод close () закрывает соединение между программой и открытым файлом, чтобы закрыть ресурсы которые не могут не может очиститьgarbagecollector, так как он не знает какие ресурсы есть помимоJVM.
Создание каталогов
Существуют два служебных метода File, которые могут быть использованы для создания каталогов:
- Метод mkdir() позволяет создать папку в Java, возвращая значение true при успехе операции, и false в случае сбоя. Сбой свидетельствует о том, что путь указанный в объекте File уже существует, либо что каталог не может быть создан в связи с тем, что полный путь еще не существует.
- Метод mkdirs() создает каталог и все вышестоящие каталоги.
В следующем примере представлено создание папки "/java/proglang/newdir":
Символьные потоки
Мы можем переформулировать представленный выше пример, в котором два данных класса используются для копирования файла ввода (с символами юникода) в файл вывода.
Примечание по примеру: чтобы скопировать файл, необходимо в папке проекта создать файл file.txt с любым или пустым содержимым.
Байтовый поток
Примечание по примеру: чтобы скопировать файл, необходимо в папке проекта создать файл file.txt с любым или пустым содержимым.
Каталоги в Java
В Java каталог представлен Файлом, который может содержать список других файлов и каталогов. Используя объект File, вы можете создать каталог, прокрутить список файлов, представленных в каталоге. Для получения более детальных сведений, ознакомьтесь с перечнем всех методов, которые могут быть вызваны из объекта File, будучи связанными с каталогами.
Список файлов в папке
Метод list(), представленный объектом File, может быть использован для предоставления перечня всех файлов и каталогов, имеющихся в заданной папке, в следующем виде:
Чтение и запись файла
Как было указано выше, поток представляет собой последовательность данных. InputStream используется для считывания данных с источника, OutputStream служит для записи данных по месту назначения.
Ниже представлена иерархия классов для управления потоками Ввода и Вывода.
В данном уроке нам предстоит рассмотреть два важных потока: FileInputStream и FileOutputStream.
Пример
Теперь рассмотрим файл file.txt со следующим содержимым:
В качестве следующего шага необходимо скомпилировать программу и выполнить ее, что позволит создать файл copied_file.txt с тем же содержимым, что имеется в file.txt. Таким образом, разместим обозначенный код в файле FileCopy.java и выполним следующее действие:
Пример
Разместим представленный выше код в файле ReadConsole.java и попробуем скомпилировать и выполнить его согласно тому, как это представлено в следующей программе. Данная программа продолжает чтение и вывод одного и того же символа до нажатия 'q':
Свойства и методы класса File
Для определения стандартных свойств файла в классе File имеются различные методы. Однако класс File несимметричен, т.е. методы определения свойств объекта существуют, но соответствующие функции для изменения этих свойств отсутствуют.
Функции | Описание |
---|---|
String getName() | Наименование файла или каталога. |
String getParent() | Наименование родительского каталога. |
long length() | Функция определения размера файла в байтах. |
String getAbsolutePath() | Функция определения абсолютного пути файла или каталога. |
boolean delete() | Удаления файла или каталога. |
boolean exists() | Проверка существования файла или каталога. |
boolean isDirectory() | Проверка, является ли данный объект каталогом. |
boolean isFile() | Проверка, является ли данный объект файлом. |
long lastModified() | Функция определения даты последней модификации файла. |
boolean canRead() | Проверка, можно ли читать данные из файла. |
boolean canWrite() | Проверка, можно ли записывать данные в файл. |
boolean isHidden() | Проверка, являются ли каталог или файл скрытыми. |
String[] list() | Чтение массива наименований файлов и подкаталогов. |
File[] listFiles() | Чтение массива файлов и подкаталогов. |
boolean mkdir() | Создание нового каталога. |
boolean renameTo(File dest) | Переименовывание файла или каталога. |
В следующем примере открываем файл "d:/test/MyFile.txt" (Windows) и извлекаем его характеристики:
В консоли будет отпечатана следующая информация:
Навигация по файловой системе и вводу/выводу
Существует ряд других классов, которые нам предстоит рассмотреть с целью ознакомления с основами навигации в файловой системе и вводу/выводу.
Стандартные потоки
Все языки программирования обеспечивают поддержку стандартного ввода/вывода, где программа пользователя может произвести ввод посредством клавиатуры и осуществить вывод на экран компьютера. Если вы знакомы с языками программирования C либо C++, вам должны быть известны три стандартных устройства STDIN, STDOUT и STDERR. Аналогичным образом, Java предоставляет следующие три стандартных потока:
Ниже представлена простая программа, которая создает InputStreamReader для чтения стандартного потока ввода, до введения пользователем "q":
Содержание
Свойства и методы класса File
Для определения стандартных свойств файла в классе File имеются различные методы. Однако класс File несимметричен, т.е. методы определения свойств объекта существуют, но соответствующие функции для изменения этих свойств отсутствуют.
Функции | Описание |
---|---|
String getName() | Наименование файла или каталога. |
String getParent() | Наименование родительского каталога. |
long length() | Функция определения размера файла в байтах. |
String getAbsolutePath() | Функция определения абсолютного пути файла или каталога. |
boolean delete() | Удаления файла или каталога. |
boolean exists() | Проверка существования файла или каталога. |
boolean isDirectory() | Проверка, является ли данный объект каталогом. |
boolean isFile() | Проверка, является ли данный объект файлом. |
long lastModified() | Функция определения даты последней модификации файла. |
boolean canRead() | Проверка, можно ли читать данные из файла. |
boolean canWrite() | Проверка, можно ли записывать данные в файл. |
boolean isHidden() | Проверка, являются ли каталог или файл скрытыми. |
String[] list() | Чтение массива наименований файлов и подкаталогов. |
File[] listFiles() | Чтение массива файлов и подкаталогов. |
boolean mkdir() | Создание нового каталога. |
boolean renameTo(File dest) | Переименовывание файла или каталога. |
В следующем примере открываем файл "d:/test/MyFile.txt" (Windows) и извлекаем его характеристики:
В консоли будет отпечатана следующая информация:
Поток FileOutputStream – создание и запись файла
Поток FileOutputStream – это поток, который используется в Java для создания файла и последующей записи в него. Поток создаст файл в случае его отсутствия перед его открытием для вывода.
Далее представлены два конструктора, которые могут быть задействованы при создании объекта FileOutputStream.
Представленный конструктор использует имя файла в качестве строки с целью создания объекта входного потока для записи файла в Java:
Представленный ниже конструктор использует объектный файл с целью создания объекта выходного потока для записи файла. Сперва мы создаем объектный файл при использовании метода File() следующим образом:
Теперь, получив объект OutputStream, следует ознакомиться со следующим перечнем вспомогательных методов, которые могут быть использованы для записи потока либо выполнения иных операций в потоке.
№ | Метод и описание |
1 | public void close() throws IOException<> Данный метод в Java закрывает выходной файловый поток. Освобождает какие-либо системные ресурсы, связанные с файлом. Выдает IOException. |
2 | protected void finalize()throws IOException <> Данный метод выполняет очистку соединения с файлом. Позволяет удостовериться в вызове закрытого метода данного выходного файлового потока при отсутствии каких-либо ссылок на данный поток. Выдает IOException. |
3 | public void write(int w)throws IOException<> Данный метод осуществляет запись заданного байта в выходной поток. |
4 | public void write(byte[] w) Запись байтов w.length из указанного массива байтов в OutputStream. |
Существуют также другие доступные выходные потоки, более детальные сведения о которых представлены по следующим ссылкам:
Пример
Скомпилируйте и выполните следующий код для создания каталога "/java/proglang/newdir".
Примечание ? Java автоматически формирует разделители пути в UNIX и Windows с учетом соглашений. При использовании косой черты (/) при работе с Java в системе Windows, производится корректное разрешение пути.
Пример
Теперь рассмотрим файл file.txt со следующим содержимым:
В качестве следующего шага необходимо скомпилировать java-программу и выполнить ее, что позволит создать файл copied_file.txt с тем же содержимым, что имеется в file.txt. Таким образом, разместим обозначенный код в файле FileCopy.java и выполним следующее действие:
Запись в файл FileOutputStream
Класс FileOutputStream, является производным от класса OutputStream, поэтому наследует всю его функциональность.
Пример записи строки в файл:
Для создания объекта FileOutputStream используется конструктор, принимающий в качестве параметра путь к файлу для записи. Для записи строки ее сначала переводим в массив байт и с помощью метода write строка записывается в файл. Необязательно записывать весь массив байтов. Используя перегрузку метода write(), можно записать и одиночный байт:
Пример перезаписи содержимого из одного файла в другой:
Класс FileOutputStream предназначен прежде всего для записи двоичных файлов. Его можно использовать для работы с текстовыми файлами, но все же для этой задачи больше подходят другие классы.
Пакет java.io содержит почти каждый класс, который может потребоваться Вам для совершения ввода и вывода в Java. Все данные потоки представлены потоком ввода и адресом вывода. Поток в пакете java.io осуществляет поддержку различных данных, таких как примитивы, объекты, локализованные символы и т.д.
Чтение содержимого файла FileInputStream
Для чтения содержимого файла можно использовать класс FileInputStream, который является наследником класса InputStream и реализует все его методы. Конструктор класса FileInputStream :
Если файл не может быть открыт то генерируется исключение FileNotFoundException.
Пример считывания данных из файла и вывод содержимого в консоль:
Данные файла можно считать в массив байтов :
Класс FileInputStream предназначен прежде всего для работы с двоичными файлами. Его можно использовать для работы с текстовыми файлами, но все же для этой задачи больше подходят другие классы.
Пример использования FileInputStream для чтения файла свойств в кодировке UTF-8:
Файл свойств "data.properties" в кодировке UTF-8:
Потоки
Потоки в Java определяются в качестве последовательности данных. Существует два типа потоков:
- InPutStream – поток ввода используется для считывания данных с источника.
- OutPutStream – поток вывода используется для записи данных по месту назначения.
Java предоставляет сильную, но гибкую поддержку в отношении ввода/вывода, связанных с файлами и сетями, однако в данном руководстве рассмотрены лишь базовые функции, связанные с потоками и вводом/выводом. Рассмотрим далее по порядку наиболее распространенные примеры.
Читайте также: