- What is the difference between IO and NIO?
- What features of NIO do you know?
- What are "channels"?
- What types of input/output streams exist?
- Name the main classes of input/output streams
- In which packages are the input/output stream classes located?
- What subclasses of the
InputStreamclass do you know, and what are they used for? - What is
PushbackInputStreamused for? - What is
SequenceInputStreamused for? - Which class allows reading data from an input byte stream in the format of primitive data types?
- What subclasses of the
OutputStreamclass do you know, and what are they used for? - What subclasses of the
Readerclass do you know, and what are they used for? - What subclasses of the
Writerclass do you know, and what are they used for? - What is the difference between
PrintWriterandPrintStream? - What are the differences and similarities between
InputStream,OutputStream,Reader, andWriter? - Which classes allow converting byte streams to character streams and vice versa?
- Which classes allow speeding up reading/writing through the use of a buffer?
- Which class is designed for working with file system elements?
- What methods of the
Fileclass do you know? - What do you know about the
FileFilterinterface? - How to select all elements of a specific directory by criteria (for example, with a specific extension)?
- What do you know about
RandomAccessFile? - What file access modes does
RandomAccessFilehave? - Which classes support reading and writing streams in a compressed format?
- Is it possible to redirect standard input/output streams?
- What character is used as a separator when specifying a path in the file system?
- What is an "absolute path" and a "relative path"?
- What is a "symbolic link"?
- Java IO (input-output) is stream-oriented, while Java NIO (new/non-blocking IO) is buffer-oriented. Stream-oriented input/output implies reading/writing one or more bytes at a time from/to a stream sequentially. This data is not cached anywhere. Thus, it is impossible to move arbitrarily forward or backward through the data stream. In Java NIO, data is first read into a buffer, which provides more flexibility when processing data.
- Input/output streams in Java IO are blocking. This means that when a
read()orwrite()method of any class from thejava.io.*package is called in a thread, blocking occurs until the data is read or written. The thread cannot do anything else at that moment. The non-blocking mode of Java NIO allows requesting read data from a channel and receiving only what is currently available, or nothing at all if no data is available yet. Instead of remaining blocked until data becomes available for reading, the thread can do something else. The same applies to non-blocking output. A thread can request writing some data to a channel without waiting for it to be fully written. - Java NIO has selectors that allow a single thread to monitor multiple input channels. That is, it is possible to register multiple channels with a selector, and then use one thread to service channels that have data available for processing, or to select channels ready for writing.
- Channels and selectors: NIO supports various types of channels. A channel is an abstraction of lower-level file system objects (such as memory-mapped files and file locks), which allows data to be transferred at higher speeds. Channels are non-blocking, so Java also provides tools such as a selector, which allows selecting a ready channel for data transfer, and a socket, which is a tool for blocking.
- Buffers: there is buffering for all primitive type wrapper classes (except Boolean). An abstract
Bufferclass was introduced, providing operations such as clear, flip, mark, etc. Its subclasses provide methods for getting and setting data. - Encodings: encoders and decoders were introduced for mapping bytes and Unicode characters.
Channels are logical (not physical) portals, abstractions of lower-level file system objects (such as memory-mapped files and file locks), through which data input/output is performed, while buffers are the sources or receivers of this transferred data. When organizing output, the data you want to send is placed in a buffer, which is then passed to the channel. On input, data from the channel is placed into a buffer you provide in advance.
Channels resemble pipelines through which data is efficiently transported between byte buffers and entities on the other side of the channels. Channels are gateways that provide access to the operating system's I/O services with minimal overhead, while buffers are the internal endpoints of these gateways, used for sending and receiving data.
There are two types of input/output streams:
- byte streams —
java.io.InputStream,java.io.OutputStream; - character streams —
java.io.Reader,java.io.Writer.
java.io, java.nio. For working with compressed data streams, classes from the java.util.zip package are used.
InputStream— an abstract class describing an input stream;BufferedInputStream— a buffered input stream;ByteArrayInputStreamallows using a memory buffer (byte array) as a data source for the input stream;DataInputStream— an input stream for byte data, including methods for reading standard Java data types;FileInputStream— an input stream for reading information from a file;FilterInputStream— an abstract class providing an interface for decorator classes that add useful properties to existing streams;ObjectInputStream— an input stream for objects;StringBufferInputStreamconverts a string (String) into anInputStreamdata input stream;PipedInputStreamimplements the concept of an input pipe;PushbackInputStream— a type of buffering that provides reading a byte with the ability to return it back to the stream, allowing you to "peek" into the input stream and see what will come next without extracting the information.SequenceInputStreamis used to merge two or moreInputStreamstreams into a single one.
A type of buffering that provides reading a byte with the ability to return it back to the stream. The PushbackInputStream class provides a mechanism to "peek" into the input stream and see what will come next without extracting the information.
The class has an additional method unread().
The SequenceInputStream class allows merging several instances of the InputStream class together. The constructor accepts either a pair of InputStream objects or an Enumeration interface as an argument.
During operation, the class performs read requests from the first InputStream object until the end, and then switches to the second. When using the Enumeration interface, processing continues across all InputStream objects. Upon reaching the end, the associated stream is closed. Closing the stream created by the SequenceInputStream object causes all open streams to be closed.
The DataInputStream class represents an input stream designed for reading primitive data types such as int, double, etc. Each primitive type has its own method for reading:
boolean readBoolean(): reads a single-byte boolean value from the streambyte readByte(): reads 1 byte from the streamchar readChar(): reads acharvalue from the streamdouble readDouble(): reads an 8-bytedoublevalue from the streamfloat readFloat(): reads a 4-bytefloatvalue from the streamint readInt(): reads anintinteger value from the streamlong readLong(): reads alongvalue from the streamshort readShort(): reads ashortvalueString readUTF(): reads a UTF-8 encoded string from the stream
OutputStream— an abstract class defining byte stream output;BufferedOutputStream— a buffered output stream;ByteArrayOutputStream— all data sent to this stream is placed in a pre-created buffer;DataOutputStream— a byte output stream including methods for writing standard Java data types;FileOutputStream— writing data to a file on a physical medium;FilterOutputStream— an abstract class providing an interface for decorator classes that add useful properties to existing streams;ObjectOutputStream— an output stream for writing objects;PipedOutputStreamimplements the concept of an output pipe;PrintStream— an output stream includingprint()andprintln()methods.
Reader— an abstract class describing character input;BufferedReader— a buffered character input stream;CharArrayReader— an input stream that reads from a character array;FileReader— an input stream that reads a file;FilterReader— an abstract class providing an interface for decorator classes;InputStreamReader— an input stream that translates bytes into characters;LineNumberReader— an input stream that counts lines;PipedReader— an input pipe;PushbackReader— an input stream that allows returning characters back to the stream;StringReader— an input stream that reads from a string.
Writer— an abstract class describing character output;BufferedWriter— a buffered character output stream;CharArrayWriter— an output stream that writes to a character array;FileWriter— an output stream that writes to a file;FilterWriter— an abstract class providing an interface for decorator classes;OutputStreamWriter— an output stream that translates bytes into characters;PipedWriter— an output pipe;PrintWriter— a character output stream includingprint()andprintln()methods;StringWriter— an output stream that writes to a string;
First of all, the PrintWriter class uses an improved method of handling Unicode characters and a different output buffering mechanism: in the PrintStream class, the output buffer was flushed every time the print() or println() method was called, whereas with the PrintWriter class, it is possible to opt out of automatic buffer flushing, performing it explicitly using the flush() method.
Additionally, the methods of the PrintWriter class never throw exceptions. To check for errors, you must explicitly call the checkError() method.
InputStreamand its descendants — a set of classes for receiving byte data from various sources;OutputStreamand its descendants — a set of classes defining byte stream output;Readerand its descendants define Unicode character stream input;Writerand its descendants define Unicode character stream output.
OutputStreamWriter— a "bridge" between theOutputStreamclass and theWriterclass. Characters written to the stream are converted to bytes.InputStreamReader— the analogous class for reading. Using methods of theReaderclass, bytes are read from theInputStreamstream and then converted to characters.
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 works directly with files and directories. This class allows creating new elements and obtaining information about existing ones: size, access rights, creation time and date, path to the parent directory.
The most commonly used methods of the File class:
boolean createNewFile(): attempts to create a new file;boolean delete(): attempts to delete a directory or file;boolean mkdir(): attempts to create a new directory;boolean renameTo(File dest): attempts to rename a file or directory;boolean exists(): checks whether the file or directory exists;String getAbsolutePath(): returns the absolute path for the path passed to the object's constructor;String getName(): returns the short name of the file or directory;String getParent(): returns the name of the parent directory;boolean isDirectory(): returnstrueif a directory is located at the specified path;boolean isFile(): returnstrueif a file is located at the specified path;boolean isHidden(): returnstrueif the directory or file is hidden;long length(): returns the file size in bytes;long lastModified(): returns the time of the last modification of the file or directory;String[] list(): returns an array of files and subdirectories located in a specific directory;File[] listFiles(): returns an array of files and subdirectories located in a specific directory.
The FileFilter interface is used to check whether a File object meets some condition. This interface contains a single method boolean accept(File pathName). This method must be overridden and implemented. For example:
public boolean accept(final File file) {
return file.isExists() && file.isDirectory();
}How to select all elements of a specific directory by criteria (for example, with a specific extension)?
The File.listFiles() method returns an array of File objects contained in the directory. The method can accept as a parameter an object of a class implementing FileFilter. This allows including in the list only those elements for which the accept method returns true (the criterion can be the file name length or its extension).
The java.io.RandomAccessFile class provides reading and writing data at an arbitrary location in a file. It is not part of the InputStream or OutputStream hierarchy. It is a completely separate class with its own (mostly native) methods. The explanation for this may be that RandomAccessFile has largely different behavior compared to other I/O classes, as it allows moving forward and backward within a file.
RandomAccessFile has such specific methods as:
getFilePointer()for determining the current location in the file;seek()for moving to a new position in the file;length()for finding out the file size;setLength()for setting the file size;skipBytes()for attempting to skip a specified number of bytes;getChannel()for working with the unique file channel associated with the given file;- methods for performing normal and formatted output from a file (
read(),readInt(),readLine(),readUTF(), etc.); - methods for normal or formatted writing to a random-access file (
write(),writeBoolean(),writeByte(), etc.).
It should also be noted that the RandomAccessFile constructors require a second argument specifying the desired file access mode — read-only ("r"), read and write ("rw"), or other variants.
"r"opens the file for reading only. Running any data write methods will result in anIOExceptionbeing thrown."rw"opens the file for reading and writing. If the file has not been created yet, an attempt is made to create it."rws"opens the file for reading and writing similar to"rw", but requires the system to synchronously write any changes to the file's content or metadata to the physical device with each modification."rwd"opens the file for reading and writing similar to"rws", but requires the system to synchronously write changes to the physical device only when the file's content changes. If metadata changes, synchronous writing is not required.
DeflaterOutputStream— data compression in deflate format.Deflater— data compression in ZLIB format.ZipOutputStream— a descendant ofDeflaterOutputStreamfor data compression in Zip format.GZIPOutputStream— a descendant ofDeflaterOutputStreamfor data compression in GZIP format.InflaterInputStream— data decompression in deflate format.Inflater— data decompression in ZLIB format.ZipInputStream— a descendant ofInflaterInputStreamfor data decompression in Zip format.GZIPInputStream— a descendant ofInflaterInputStreamfor data decompression in GZIP format.
The System class allows you to redirect standard input, output, and error output streams using a simple call to a static method:
setIn(InputStream)— for input;setOut(PrintStream)— for output;setErr(PrintStream)— for error output.
The separator character differs for different operating systems. For Windows it is \, for Linux it is /.
In Java, you can obtain the separator for the current operating system by accessing the static field File.separator.
An absolute (full) path is a path that points to the same location in the file system regardless of the current working directory or other circumstances. A full path always starts from the root directory.
A relative path is a path relative to the current working directory of the user or the active application.
A symbolic (symlink) (also "symlink", Symbolic link) is a special file in the file system that, instead of user data, contains a path to a file that should be opened when attempting to access this link (file). The target of a link can be any object: for example, another link, a file, a directory, or even a non-existent file (in the latter case, when attempting to open it, a message about the missing file should be displayed).
Symbolic links are used for more convenient organization of the file structure on a computer, because:
- they allow a single file or directory to have multiple names and different attributes;
- they are free from some limitations inherent to hard links (the latter work only within a single file system (one partition) and cannot point to directories).