Java I/O, NIO and NIO.2
Buffers are not thread-safe. You must employ synchronization when you want to access a buffer from multiple threads.
Are buffers thread safe?
JDK 1.4 supports regular expressions via the java.util.regex package and its Pattern and Matcher classes.
How does JDK support regular expressions?
You can mark a buffer by invoking the mark() method and later return to the marked position by invoking reset().
How to mark a buffer?
Files are common stream destinations and sources. The concrete FileOutputStream class lets you write a stream of bytes to a file; the concrete FileInputStream class lets you read a stream of bytes from a file. FileOutputStream and FileInputStream are useful in a file-copying context.
What does FileOutputStream and FileInputStream do?
File declares the File[] listRoots() class method to return the root directories (roots) of available file systems as an array of File objects. File[] roots = File.listRoots(); for (File root: roots) System.out.println(root);
What does File[] listRoots() method of the File class do?
InputStream is the superclass of all input stream subclasses.
What does abstract class InputStream do?
Return the parent path string of this File object's path, or return null when this path doesn't name a parent directory.
What does getParent() method of the File class do?
Return true when this File object's abstract path refers to an existing directory.
What does isDirectory() method of the File class do?
A convenience method for calling list(), converting its array of Strings to an array of Files, and returning the Files array.
What does listFiles() method of the File class do?
ll channels are instances of classes that ultimately implement the java.nio.channels.Channel interface. Channel declares the following methods: - void close(): Close this channel. When this channel is already closed, invoking close() has no effect. When another thread has already invoked close(), a new close() invocation blocks until the first invocation finishes, after which close() returns without effect. This method throws java.io.IOException when an I/O error occurs. After the channel is closed, any further attempts to invoke I/O operations on it result in java.nio.channels.ClosedChannelException being thrown. - boolean isOpen(): Return this channel's open status. This method returns true when the channel is open; otherwise, it returns false.
What interface do all channels implement?
Many operating systems allow streams to be configured to operate in nonblocking mode in which a thread continually checks for available input without blocking when no input is available. The thread can handle incoming data or perform other tasks until data arrives. This "polling for available input" activity can be wasteful, especially when the thread needs to monitor many input streams (such as in a web server context).
What is "polling for available input"?
A file system is an operating system component that manages data storage and subsequent retrieval.
What is a file system?
Absolute path is a path that starts with the root directory symbol; no other information is required to locate the file/directory that it denotes.
What is an absolute path?
Although getFreeSpace() and getUsableSpace() appear to be equivalent, they differ in the following respect: unlike getFreeSpace(), getUsableSpace() checks for write permissions and other operating system restrictions, resulting in a more accurate estimate.
What is the difference between getFreeSpace() and getUsableSpace methods of the File class?
The clear() method marks a buffer as empty whereas reset() changes the buffer's current position to the previously set mark, or throws InvalidMarkException when there's no previously set mark.
What is the difference between reset() and clear() methods on buffer?
ByteArrayOutputStream and ByteArrayInputStream are useful when you need to convert an image to an array of bytes, process these bytes in some manner, and convert the bytes back to the image.
When are ByteArrayOutputStream and ByteArrayInputStream useful?
Random access can speed up searching and sorting capabilities.
Why to use random access?
JDK 1.0's I/O capabilities are suitable for streaming bytes, but cannot properly stream characters because they don't account for character encodings. JDK 1.1 overcame this problem by introducing writer/reader classes that take character encodings into account. For example, the java.io package includes FileWriter and FileReader classes for writing and reading character streams.
How are character encodings handled in classic I/O?
The java.io package's classes default to resolving relative paths against the current user (also known as working) directory, which is identified by the system property user.dir and which is typically the directory in which the JVM was launched. (You obtain a system property value by calling the java.lang.System class's getProperty() method.)
How do you obtain the current user (also known as working) directory?
JDK 1.4 supports readiness selection by providing selectors, which are instances of the java.nio.channels.Selector class that can examine one or more channels and determine which channels are ready for reading or writing. This way a single thread can manage multiple channels (and, therefore, multiple network connections) efficiently. Being able to use fewer threads is advantageous where thread creation and thread context switching is expensive in terms of performance and/or memory use.
How does JDK support "readiness selection"?
Java supports channels via its java.nio.channels and java.nio.channels.spi packages. Applications interact with the types located in the former package; developers who are defining new selector providers work with the latter package.
How does Java support channels?
Files can be created and/or opened for random access in which a mixture of write and read operations at various locations can occur until the file is closed. Java supports this random access by providing a java.io.RandomAccessFile class.
How does Java support random access?
I/O is classified as block-oriented or stream-oriented. Reading from or writing to a file is an example of block-oriented I/O. In contrast, reading from the keyboard or writing to a network connection is an example of stream-oriented I/O.
How is I/O classified?
1. RandomAccessFile(File file, String mode): Create and open a new file when it doesn't exist or open an existing file. The file is identified by file's abstract path and is created and/or opened according to mode. 2. RandomAccessFile(String path, String mode): Create and open a new file when it doesn't exist or open an existing file. The file is identified by path and is created and/or opened according to mode.
How many constructors were declared in RandomAccessFile class?
Buffers possess four properties: - Capacity: The total number of data items that can be stored in the buffer. The capacity is specified when the buffer is created and cannot be changed later. - Limit: The zero-based index of the first element that should not be read or written. In other words, it identifies the number of "live" data items in the buffer. - Position: The zero-based index of the next data item that can be read or the location where the data item can be written. - Mark: A zero-based index to which the buffer's position will be reset when the buffer's reset() method (presented shortly) is called. The mark is initially undefined. These four properties are related as follows: 0 <= mark <= position <= limit <= capacity
How many properties does a buffer posses?
To create a File instance, call a constructor such as File(String path), which creates a File instance that stores the path string: File file1 = new File("/x/y");
How to create a File instance?
ByteBuffer and the other primitive-type buffer classes declare various class methods for creating a buffer of that type. For example, ByteBuffer declares the following class methods for creating ByteBuffer instances: - ByteBuffer allocate(int capacity) - ByteBuffer allocateDirect(int capacity) - ByteBuffer wrap(byte[] array) - ByteBuffer wrap(byte[] array, int offset, int length) ByteBuffer buffer = ByteBuffer.allocate(10); byte[] bytes = new byte[200]; ByteBuffer buffer2 = ByteBuffer.wrap(bytes);
How to create a buffer?
The JDK provides a serialver tool for calculating the SUID. For example, to generate an SUID for Employee class, change to the directory containing Employee.class and execute the following command: $ serialver Employee
How to generate SUID?
ByteBuffers (and other primitive-type buffers) created via allocate() or wrap() are nondirect byte buffers. Nondirect byte buffers have backing arrays, and you can access these backing arrays via the array() method (which happens to be declared as byte[] array() in the ByteArray class) as long as hasArray() returns true. (When hasArray() returns true, you'll need to call arrayOffset() to obtain the location of the first data item in the array.)
What are nondirect byte buffers?
- available() - mark() - markSupported() - read() - reset() - skip()
What are some methods of InputStream class?
- close() - flush() - write()
What are some methods of OutputStream class?
Although the primitive-type buffer classes have similar capabilities, ByteBuffer is the largest and most versatile. After all, bytes are the basic unit used by operating systems to transfer data items.
What buffer implementation is most versatile?
Threads must often communicate. One approach involves using shared variables. Another approach involves using piped streams via the PipedOutputStream and PipedInputStream classes. The PipedOutputStream class lets a sending thread write a stream of bytes to an instance of the PipedInputStream class, which a receiving thread uses to subsequently read those bytes. Attempting to use a PipedOutputStream object and a PipedInputStream object from a single thread is not recommended because it might deadlock the thread.
What does PipedOutputStream and PipedInputStream do?
Return a potentially empty array of strings naming the files and directories in the directory denoted by this File object's abstract path. If the path doesn't denote a directory, or if an I/O error occurs, this method returns null. Otherwise, it returns an array of strings, one string for each file or directory in the directory. Names denoting the directory itself and the directory's parent directory are not included in the result. Each string is a file name rather than a complete path. Also, there is no guarantee that the name strings in the resulting array will appear in alphabetical or any other order.
What does String[] list() method of the File class do?
Java provides the Writer and Reader classes for performing character I/O. Writer is the superclass of all writer subclasses.
What does Writer and Reader classes do?
OutputStream is the superclass of all output stream subclasses.
What does abstract class OutputStream do?
Return true if and only if the file or directory that's denoted by this File object's abstract path exists.
What does exists() method of the File class do?
Unlike default/custom serialization/deserialization, externalization offers complete control over the serialization and deserialization tasks. Note Externalization helps you improve the performance of the reflection-based serialization and deserialization mechanisms by giving you complete control over what fields are serialized and deserialized. Java supports externalization via java.io.Externalizable.
What does externalization do?
Return the absolute form of this File object's abstract path. This method is equivalent to new File(this.getAbsolutePath()).
What does getAbsoluteFile() method of the File class do?
Return the absolute path string of this File object's abstract path. When it's already absolute, the path string is returned as if by calling getPath(). When it's the empty abstract path, the path string of the current user directory (identified via user.dir) is returned. Otherwise, the abstract path is resolved in an operating system-dependent manner. On Unix/Linux operating systems, a relative path is made absolute by resolving it against the current user directory. On Windows operating systems, the path is made absolute by resolving it against the current directory of the drive named by the path, or the current user directory when there is no drive.
What does getAbsolutePath() method of the File class do?
returns the number of unallocated bytes in the partition identified by this File object's abstract path; it returns zero when the abstract path doesn't name a partition.
What does getFreeSpace() method of the File class do?
Return the file name or directory name denoted by this File object's abstract path. This name is the last in a path's name sequence. The empty string is returned when the path's name sequence is empty.
What does getName() method of the File class do?
Convert this File object's abstract path into a path string where the names in the sequence are separated by the character stored in File's separator field. Return the resulting path string.
What does getPath() method of the File class do?
returns the size (in bytes) of the partition identified by this File object's abstract path; it returns zero when the abstract path doesn't name a partition.
What does getTotalSpace() method of the File class do?
returns the number of bytes available to the current JVM on the partition identified by this File object's abstract path; it returns zero when the abstract path doesn't name a partition.
What does getUsableSpace() method of the File class do?
It supports bulk access to file attributes, provides a change notification facility, offers the ability to escape to file system-specific APIs, and has a service provider interface for pluggable file system implementations.
What does improved filesystem interface support?
Return true when this File object's abstract path is absolute; otherwise, return false when it's relative. The definition of absolute path is system dependent. For Unix/Linux operating systems, a path is absolute when its prefix is "/". For Windows operating systems, a path is absolute when its prefix is a drive specifier followed by "\" or when its prefix is "\\".
What does isAbsolute() method of the File class do?
Return true when this File object's abstract path refers to an existing normal file. A file is normal when it's not a directory and satisfies other operating system-dependent criteria. It's not a symbolic link or a named pipe, for example. Any nondirectory file created by a Java application is guaranteed to be a normal file.
What does isFile() method of the File class do?
Return true when the file denoted by this File object's abstract path is hidden. The exact definition of hidden is operating system dependent. On Unix/Linux operating systems, a file is hidden when its name begins with a period character. On Windows operating systems, a file is hidden when it has been marked as such in the file system.
What does isHidden() method of the File class do?
Return the time that the file denoted by this File object's abstract path was last modified, or 0 when the file doesn't exist or an I/O error occurred during this method call. The returned value is measured in milliseconds since the Unix epoch (00:00:00 GMT, January 1, 1970).
What does lastModified() method of the File class do?
The transient keyword prevents the values of instance fields that are declared with this keyword from being persisted when an object is serialized (written as a sequence of bytes to some destination). The values of such instance fields shouldn't be persisted and later restored when an object is deserialized (reconstituted from a sequence of bytes read from some source). For example, if your object has a field of type java.io.InputStream, you don't serialize this field's reference because the stream won't be open for input when you deserialize the object -- the stream source (e.g., a file) might not exist.
What does the transient keyword accomplish?
The operating system monitors a collection of streams and returns an indication to the thread of which streams are ready to perform I/O. As a result, a single thread can multiplex many active streams via common code and makes it possible, in a web server context, to manage a huge number of network connections.
What is "readiness selection"?
Java's stream classes are good for streaming sequences of bytes, but they're not good for streaming sequences of characters because bytes and characters are two different things: a byte represents an 8-bit data item and a character represents a 16-bit data item. Also, Java's char and java.lang.String types naturally handle characters instead of bytes. More importantly, byte streams have no knowledge of character sets (sets of mappings between integer values, known as code points, and symbols, such as Unicode) and their character encodings (mappings between the members of a character set and sequences of bytes that encode these characters for efficiency, such as UTF-8). If you need to stream characters, you should take advantage of Java's writer and reader classes, which were designed to support character I/O (they work with char instead of byte). Furthermore, the writer and reader classes take character encodings into account.
Why do we need writers and readers?
Because File(String path), File(String parent, String child), and File(File parent, String child) don't detect invalid path arguments (apart from throwing a java.lang.NullPointerException when path or child is null), you must be careful when specifying paths. You should strive to only specify paths that are valid for all operating systems on which the application will run. For example, instead of hard-coding a drive specifier (such as C:) in a path, use a root returned from listRoots(), which I discuss later. Even better, keep your paths relative to the current user/working directory (returned from the user.dir system property).
Why only specify paths that are valid for all operating systems on which the application will run?
After filling a buffer, you must prepare it for draining by a channel. When you pass the buffer as is, the channel accesses undefined data beyond the current position. To solve this problem, you could reset the position to 0, but how would the channel know when the end of the inserted data had been reached? The solution is to work with the limit property, which indicates the end of the active portion of the buffer. Basically, you set the limit to the current position and then reset the current position to 0. You could accomplish this task by executing the following code, which also clears any defined mark: buffer.limit(buffer.position()).position(0); However, there's an easier way to accomplish the same task, as shown here: buffer.flip(); String[] poem = { "Roses are red", "Violets are blue", "Sugar is sweet", "And so are you." }; CharBuffer buffer = CharBuffer.allocate(50); for (int i = 0; i < poem.length; i++) { // Fill the buffer. for (int j = 0; j < poem[i].length(); j++) buffer.put(poem[i].charAt(j)); // Flip the buffer so that its contents can be read. buffer.flip(); // Drain the buffer. while (buffer.hasRemaining()) System.out.print(buffer.get()); // Empty the buffer to prevent BufferOverflowException. buffer.clear(); System.out.println(); }
Why to flip a buffer?
Regular expressions were introduced as part of NIO. Although you might wonder about the rationale for doing this (what have regular expressions got to do with I/O?), regular expressions are commonly used to scan textual data that is read from a file or other source. The need to perform these scans as quickly as possible mandated their inclusion.
Why were regular expressions introduced as part of NIO?
You would use FileInputStream to open an existing file and connect an input stream to it. You would then invoke various read() methods to read bytes from the file over the input stream. Lastly, you would invoke close() to close the stream and file. FileInputStream fis = null; try { fis = new FileInputStream("image.jpg"); // Read bytes from file. int _byte; while ((_byte = fis.read()) != -1) // -1 signifies EOF ; // Process _byte in some way. } catch (IOException ioe) { // Handle exception. } finally { if (fis != null) try { fis.close(); } }
Why would you use FileInputStream?
public static void main(String[] args) { ReadableByteChannel src = Channels.newChannel(System.in); WritableByteChannel dest = Channels.newChannel(System.out); try { copy(src, dest); } catch (IOException ioe) { System.err.println("I/O error: " + ioe.getMessage()); } finally { try { src.close(); dest.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } static void copy(ReadableByteChannel src, WritableByteChannel dest) throws IOException { ByteBuffer buffer = ByteBuffer.allocateDirect(2048); while (src.read(buffer) != -1) { buffer.flip(); dest.write(buffer); buffer.compact(); } buffer.flip(); while (buffer.hasRemaining()) dest.write(buffer); }
Write an example for channels and buffers
File content can be accessed sequentially or randomly.
How can file content be accessed?
Java provides the java.nio.channels.ScatteringByteChannel interface to support scattering and the java.nio.channels.GatheringByteChannel interface to support gathering. ScatteringByteChannel offers the following methods: long read(ByteBuffer[] buffers, int offset, int length) long read(ByteBuffer[] buffers) GatheringByteChannel offers the following methods: long write(ByteBuffer[] buffers, int offset, int length) long write(ByteBuffer[] buffers)
How does Java support Scatter/Gather I/O?
Read-only view buffers can be created by calling a method such as ByteBuffer asReadOnlyBuffer(). Any attempt to change a read-only view buffer's content results in ReadOnlyBufferException. However, the original buffer content (provided that it isn't read-only) can be changed, and the read-only view buffer will reflect these changes.
How to create read-only view buffer?
An instance of the java.io.File class abstracts a file or directory path. This instance provides access to the file system to perform tasks on this path such as removing the underlying file or directory. new File("temp").mkdir();
What class abstracts a file or directory path?
An instance of the java.io.RandomAccessFile class provides random access to a file. RandomAccessFile raf = new RandomAccessFile("employees.dat", "r"); int empIndex = 10; raf.seek(empIndex * EMP_REC_LEN);
What class provides random access to a file?
JDK 1.0 introduced rudimentary I/O facilities for accessing the file system (to create a directory, remove a file, or perform another task), accessing file content randomly (as opposed to sequentially), and streaming byte-oriented data between sources and destinations in a sequential manner.
What classic I/O facilities did JDK 1.0 introduce?
Return the canonical (simplest possible, absolute and unique) form of this File object's abstract path. This method throws java.io.IOException when an I/O error occurs (creating the canonical path may require file system queries); it equates to new File(this.getCanonicalPath()).
What does getCanonicalFile() method of the File class do?
Return the canonical path string of this File object's abstract path. This method first converts this path to the absolute form when necessary, as if by invoking getAbsolutePath(), and then maps it to its unique form in an operating system-dependent way. Doing so typically involves removing redundant names such as "." and ".." from the path, resolving symbolic links (on Unix/Linux operating systems), and converting drive letters to a standard case (on Windows operating systems). This method throws IOException when an I/O error occurs (creating the canonical path may require file system queries).
What does getCanonicalPath() method of the File class do?
Channels provide the ability to perform a single I/O operation across multiple buffers. This capability is known as scatter/gather I/O (and is also known as vectored I/O). In the context of a write operation, the contents of several buffers are gathered (drained) in sequence and then sent through the channel to a destination. These buffers are not required to have identical capacities. In the context of a read operation, the contents of a channel are scattered (filled) to multiple buffers in sequence; each buffer is filled to its limit until the channel is empty or until the total buffer space is used.
What is Scatter/Gather I/O?
Bytes flow over an input stream from a source to an application.
What is an input stream?
Java provides the DataOutputStream and DataInputStream classes to stream primitive-type values and String objects. However, you cannot use these classes to stream non-String objects. Instead, you must use object serialization and deserialization to stream objects of arbitrary types. Object serialization is a Java virtual machine (JVM) mechanism for serializing object state into a stream of bytes. Its deserialization counterpart is a JVM mechanism for deserializing this state from a byte stream. Note An object's state consists of instance fields that store primitive-type values and/or references to other objects. When an object is serialized, the objects that are part of this state are also serialized (unless you prevent them from being serialized). Furthermore, the objects that are part of those objects' states are serialized (unless you prevent this), and so on. Java supports default serialization and deserialization, custom serialization and deserialization, and externalization.
What is object serialization and deserialization?
InputStream subclasses such as ByteArrayInputStream support marking the current read position in the input stream via the mark() method and later return to that position via the reset() method.
What subclass of InputStream does support mark() and reset() methods?
Normally, the serialization mechanism writes out a class's instance fields to the underlying output stream. However, you can prevent this from happening by declaring a private void writeObject(ObjectOutputStream oos) method in that class. When the serialization mechanism discovers this method, it calls the method instead of automatically outputting instance field values. The only values that are output are those explicitly output via the method. Conversely, the deserialization mechanism assigns values to a class's instance fields that it reads from the underlying input stream. However, you can prevent this from happening by declaring a private void readObject(ObjectInputStream ois) method. When the deserialization mechanism discovers this method, it calls the method instead of automatically assigning values to instance fields. The only values that are assigned to instance fields are those explicitly assigned via the method.
How to implement custom serialization and deserialization in Java?
There are two ways to obtain a channel: - The java.nio.channels package provides a Channels utility class that offers two methods for obtaining channels from streams. For each of the following methods, the underlying stream is closed when the channel is closed, and the channel isn't buffered: 1. WritableByteChannel newChannel(OutputStream outputStream) returns a writable byte channel for the given outputStream. 2. ReadableByteChannel newChannel(InputStream inputStream) returns a readable byte channel for the given inputStream. - Various classic I/O classes have been retrofitted to support channel creation. For example, java.io.RandomAccessFile declares a FileChannel getChannel() method for returning a file channel, and java.net.Socket declares a SocketChannel getChannel() method for returning a socket channel.
How to obtain a channel?
Your first task is to have the class of the object that's to be serialized implement the java.io.Serializable interface, either directly or indirectly via the class's superclass. The rationale for implementing Serializable is to avoid unlimited serialization. Your second task is to work with the ObjectOutputStream class and its writeObject() method to serialize an object and the OutputInputStream class and its readObject() method to deserialize the object. ObjectOutputStream oos = null; ObjectInputStream ois = null; try { FileOutputStream fos = new FileOutputStream(FILENAME); oos = new ObjectOutputStream(fos); Employee emp = new Employee("John Doe", 36); oos.writeObject(emp); oos.close(); oos = null; FileInputStream fis = new FileInputStream(FILENAME); ois = new ObjectInputStream(fis); emp = (Employee) ois.readObject(); // (Employee) cast is necessary. ois.close(); System.out.println(emp.getName()); System.out.println(emp.getAge()); } catch (ClassNotFoundException cnfe) { System.err.println(cnfe.getMessage()); } catch (IOException ioe) { System.err.println(ioe.getMessage()); } finally { if (oos != null) try { oos.close(); } catch (IOException ioe) { assert false; // shouldn't happen in this context } if (ois != null) try { ois.close(); } catch (IOException ioe) { assert false; // shouldn't happen in this context } }
How to use default serialization and deserialization?
ByteBuffer and the other primitive-type buffer classes declare several overloaded put() and get() methods for writing data items to and reading data items from a buffer. These methods are absolute when they require an index argument or relative when they don't require an index. ByteBuffer buffer = ByteBuffer.allocate(7); buffer.put((byte) 10).put((byte) 20).put((byte) 30); for (int i = 0; i < buffer.position(); i++) System.out.println(buffer.get(i));
How to write to and read from a buffer?
JDK 1.4 implemented NIO in terms of the following APIs: - Buffers - Channels - Selectors - Regular expressions - Charsets The regular expression and charset APIs were provided to simplify common I/O-related tasks.
What APIs does NIO include?
File offers additional constructors for instantiating this class. For example, the following constructors merge parent and child paths into combined paths that are stored in File objects: - File(String parent, String child) creates a new File instance from a parent path string and a child path string. - File(File parent, String child) creates a new File instance from a parent path File instance and a child path string. File file3 = new File("prj/books/", "io");
What are additional constructors for File class?
Buffers are the foundation for NIO operations. Essentially, NIO is all about moving data into and out of buffers. A process such as the JVM performs I/O by asking the operating system to drain a buffer's contents to storage via a write operation. Similarly, it asks the operating system to fill a buffer with data read from a storage device.
What are buffers?
- "r" informs the constructor to open an existing file for reading only. Any attempt to write to the file results in a thrown instance of the java.io.IOException class. - "rw" informs the constructor to create and open a new file when it doesn't exist for reading and writing or open an existing file for reading and writing. - "rwd" informs the constructor to create and open a new file when it doesn't exist for reading and writing or open an existing file for reading and writing. Furthermore, each update to the file's content must be written synchronously to the underlying storage device. - "rws" informs the constructor to create and open a new file when it doesn't exist for reading and writing or open an existing file for reading and writing. Furthermore, each update to the file's content or metadata must be written synchronously to the underlying storage device.
What are constructor's mode argument for RandomAccessFile?
FileOutputStream and FileInputStream have a performance problem. Each file output stream write() method call and file input stream read() method call results in a native method call to one of the underlying operating system's functions, and these native method calls slow down I/O. The concrete BufferedOutputStream and BufferedInputStream filter stream classes improve performance by minimizing underlying output stream write() and underlying input stream read() method calls. Instead, calls to BufferedOutputStream's write() and BufferedInputStream's read() methods take Java buffers into account: When a write buffer is full, write() calls the underlying output stream write() method to empty the buffer. Subsequent calls to BufferedOutputStream's write() methods store bytes in this buffer until it's once again full. When the read buffer is empty, read() calls the underlying input stream read() method to fill the buffer. Subsequent calls to BufferedInputStream's read() methods return bytes from this buffer until it's once again empty. BufferedOutputStream declares the following constructors: BufferedOutputStream(OutputStream out) creates a buffered output stream that streams its output to out. An internal buffer is created to store bytes written to out. BufferedOutputStream(OutputStream out, int size) creates a buffered output stream that streams its output to out. An internal buffer of length size is created to store bytes written to out.
What does BufferedOutputStream and BufferedInputStream do?
BufferedWriter writes text to a character-output stream (a Writer instance), buffering characters so as to provide for the efficient writing of single characters, arrays, and strings. Invoke either of the following constructors to construct a buffered writer: BufferedWriter(Writer out) BufferedWriter(Writer out, int size) The buffer size may be specified, or the default size (8,192 bytes) may be accepted. The default is large enough for most purposes. BufferedWriter includes a handy void newLine() method for writing a line-separator string, which effectively terminates the current line. BufferedReader reads text from a character-input stream (a Reader instance), buffering characters so as to provide for the efficient reading of characters, arrays, and lines. Invoke either of the following constructors to construct a buffered reader: BufferedReader(Reader in) BufferedReader(Reader in, int size) The buffer size may be specified, or the default size (8,192 bytes) may be used. The default is large enough for most purposes. BufferedReader includes a handy String readLine() method for reading a line of text, not including any line-termination characters.
What does BufferedWriter and BufferedReader do?
FileOutputStream and FileInputStream are useful for writing and reading bytes and arrays of bytes. However, they provide no support for writing and reading primitive-type values (such as integers) and strings. For this reason, Java provides the concrete DataOutputStream and DataInputStream filter stream classes. Each class overcomes this limitation by providing methods to write or read primitive-type values and strings in an operating system-independent way: - Integer values are written and read in big-endian format (the most significant byte comes first) - Floating-point and double precision floating-point values are written and read according to the IEEE 754 standard, which specifies four bytes per floating-point value and eight bytes per double precision floating-point value. - Strings are written and read according to a modified version of UTF-8, a variable-length encoding standard for efficiently storing two-byte Unicode characters.
What does DataOutputStream and DataInputStream do?
FileWriter is a convenience class for writing characters to files. It subclasses OutputStreamWriter, and its constructors, such as FileWriter(String path), call OutputStreamWriter(OutputStream). FileReader is a convenience class for reading characters from files. It subclasses InputStreamReader, and its constructors, such as FileReader(String path), call InputStreamReader(InputStream).
What does FileWriter and FileReader do?
Channel is also extended by the java.nio.channels.InterruptibleChannel interface. InterruptibleChannel describes a channel that can be asynchronously closed and interrupted. This interface overrides its Channel superinterface's close() method header, presenting the following additional stipulation to Channel's contract for this method: Any thread currently blocked in an I/O operation on this channel will receive AsynchronousCloseException (an IOException descendent). A channel that implements this interface is asynchronously closeable: When a thread is blocked in an I/O operation on an interruptible channel, another thread may invoke the channel's close() method. This causes the blocked thread to receive a thrown AsynchronousCloseException instance. A channel that implements this interface is also interruptible: When a thread is blocked in an I/O operation on an interruptible channel, another thread may invoke the blocked thread's interrupt() method. Doing this causes the channel to be closed, the blocked thread to receive a thrown ClosedByInterruptException instance, and the blocked thread to have its interrupt status set. (When a thread's interrupt status is already set and it invokes a blocking I/O operation on a channel, the channel is closed and the thread will immediately receive a thrown ClosedByInterruptException instance; its interrupt status will remain set.)
What does InterruptibleChannel interface do?
The concrete OutputStreamWriter class (a Writer subclass) is a bridge between an incoming sequence of characters and an outgoing stream of bytes. Characters written to this writer are encoded into bytes according to the default or specified character encoding. Each call to one of OutputStreamWriter's write() methods causes an encoder to be called on the given character(s). The resulting bytes are accumulated in a buffer before being written to the underlying output stream. The characters passed to the write() methods are not buffered. The concrete InputStreamReader class (a Reader subclass) is a bridge between an incoming stream of bytes and an outgoing sequence of characters. Characters read from this reader are decoded from bytes according to the default or specified character encoding. Each call to one of InputStreamReader's read() methods may cause one or more bytes to be read from the underlying input stream. To enable the efficient conversion of bytes to characters, more bytes may be read ahead from the underlying stream than are necessary to satisfy the current read operation.
What does OutputStreamWriter and InputStreamReader do?
Nonblocking mode improves performance by preventing a thread that performs a read or write operation on a channel from blocking until input is available or the output has been fully written. However, it doesn't let an application determine if it can perform an operation without actually performing the operation. For example, when a nonblocking read operation succeeds, the application learns that the read operation is possible but also has read some data that must be managed. This duality prevents you from separating code that checks for stream readiness from the data-processing code without making your code significantly complicated. Asynchronous I/O overcomes this problem by letting the thread initiate the operation and immediately proceed to other work. The thread specifies some kind of callback function that is invoked when the operation finishes.
What is Asynchronous I/O?
Modern operating systems offer sophisticated I/O services (such as readiness selection) for improving I/O performance and simplifying I/O. Java Specification Request (JSR) 51 was created to address these capabilities. JSR 51's description indicates that it provides APIs for scalable I/O, fast buffered binary and character I/O, regular expressions, and charset conversion. Collectively, these APIs are known as NIO.
What is NIO?
RandomAccessFile is useful for creating a flat file database, a single file organized into records and fields. A record stores a single entry (such as a part in a parts database) and a field stores a single attribute of the entry (such as a part number).
What is RandomAccessFile useful for?
To support I/O, Channel is extended by the java.nio.channels.WritableByteChannel and java.nio.channels.ReadableByteChannel interfaces: - WritableByteChannel declares an abstract int write(ByteBuffer buffer) method that writes a sequence of bytes from buffer to the current channel. This method returns the number of bytes actually written. It throws java.nio.channels.NonWritableChannelException when the channel was not opened for writing, java.nio.channels.ClosedChannelException when the channel is closed, java.nio.channels.AsynchronousCloseException when another thread closes the channel during the write, java.nio.channels.ClosedByInterruptException when another thread interrupts the current thread while the write operation is in progress (thereby closing the channel and setting the current thread's interrupt status), and IOException when some other I/O error occurs. - ReadableByteChannel declares an abstract int read(ByteBuffer buffer) method that reads bytes from the current channel into buffer. This method returns the number of bytes actually read (or -1 when there are no more bytes to read). It throws java.nio.channels.NonReadableChannelException when the channel was not opened for reading; ClosedChannelException when the channel is closed; AsynchronousCloseException when another thread closes the channel during the read; ClosedByInterruptException when another thread interrupts the current thread while the write operation is in progress, thereby closing the channel and setting the current thread's interrupt status; and IOException when some other I/O error occurs.
What is WritableByteChannel and ReadableByteChannel?
An instance of the File class contains an abstract representation of a file or directory path (a compact map that locates and identifies a file system object).
What is a File class?
A buffer is an object that stores a fixed amount of data to be sent to or received from an I/O service (an operating system component for performing input/output). It sits between an application and a channel that writes the buffered data to the service or reads the data from the service and deposits it into the buffer.
What is a buffer?
A channel is an object that represents an open connection to a hardware device, a file, a network socket, an application component, or another entity that's capable of performing writes, reads, and other I/O operations. Channels efficiently transfer data between byte buffers and operating system-based I/O service sources or destinations.
What is a channel?
Forcing a CPU to perform I/O tasks and wait for I/O completions (such a CPU is said to be I/O bound) is wasteful of this resource. Performance can be improved by offloading these tasks to DMA controllers so that the processor can get on with other work. A channel serves as a conduit for communicating (via the operating system) with a DMA controller to efficiently drain byte buffers to or fill byte buffers from a disk.
What is a channel?
File locking lets a process prevent or limit access to a file while the process is accessing the file. Although file locking can be applied to an entire file, it is often narrowed to a smaller region. A lock ranges from a starting byte offset in the file and continues for a specific number of bytes.
What is a file locking?
A file system stores data in files, which are stored in directories. Its file and directory objects are accessed by specifying paths, which are compact maps that locate and identify file system objects. Paths are either absolute or relative: - An absolute path is a path relative to the file system's root directory. It's expressed as the root directory symbol followed by a delimited hierarchy of directory names that ends in the target directory or file name. - A relative path is a path relative to some other directory. It's expressed similarly to an absolute path but without the initial root directory symbol. In contrast, it's often prefixed with one or more delimited ".." character sequences, where each sequence refers to a parent directory.
What is a path?
Relative path doesn't start with the root directory symbol; it's interpreted via information taken from another path.
What is a relative path?
A stream is an ordered sequence of bytes of an arbitrary length. Bytes flow over an output stream from an application to a destination and flow over an input stream from a source to an application.
What is a stream in Java?
A stream is an ordered sequence of bytes of arbitrary length.
What is a stream?
As well as managing data elements stored in external arrays (via the wrap() methods), buffers can manage data stored in other buffers. When you create a buffer that manages another buffer's data, the created buffer is known as a view buffer. Changes made in either buffer are reflected in the other. View buffers are created by calling a Buffer subclass's duplicate() method. The resulting view buffer is equivalent to the original buffer; both buffers share the same data items and have equivalent capacities. However, each buffer has its own position, limit, and mark. When the buffer being duplicated is read-only or direct, the view buffer is also read-only or direct. ByteBuffer buffer = ByteBuffer.allocate(10); ByteBuffer bufferView = buffer.duplicate(); View buffers are also created by calling one of ByteBuffer's asxBuffer() methods. For example, LongBuffer asLongBuffer() returns a view buffer that conceptualizes the byte buffer as a buffer of long integers.
What is a view buffer?
The legacy File class suffers from various problems. For example, the renameTo() method doesn't work consistently across operating systems. Also, many of File's methods don't scale; requesting a large directory listing from a server could result in a hang. The new file system interface mentioned in JSR 203 fixes these and other problems.
What is an improved filesystem interface introduced in NIO.2?
Bytes flow over an output stream from an application to a destination.
What is an output stream?
Every serialized object has an identifier. The deserialization mechanism compares the identifier of the object being deserialized with the serialized identifier of its class (all serializable classes are automatically given unique identifiers unless they explicitly specify their own identifiers) and causes InvalidClassException to be thrown when it detects a mismatch. You can avoid the thrown InvalidClassException instance by adding a static final long serialVersionUID = long integer value; declaration to the class. The long integer value must be unique and is known as a stream unique identifier (SUID). During deserialization, the JVM will compare the deserialized object's SUID to its class's SUID. If they match, readObject() will not throw InvalidClassException when it encounters a compatible class change (such as adding an instance field). However, it will still throw this exception when it encounters an incompatible class change (such as changing an instance field's name or type).
What is stream unique identifier (SUID)?
Unlimited serialization is the process of serializing an entire object graph. Java doesn't support unlimited serialization for the following reasons: - Security: If Java automatically serialized an object containing sensitive information (such as a password or a credit card number), it would be easy for a hacker to discover this information and wreak havoc. It's better to give the developer a choice to prevent this from happening. - Performance: Serialization leverages the Reflection API, which tends to slow down application performance. Unlimited serialization could really hurt an application's performance. - Objects not amenable to serialization: Some objects exist only in the context of a running application and it's meaningless to serialize them. For example, a file stream object that's deserialized no longer represents a connection to a file.
What is unlimited serialization?