Chapter 20 The I/O Package

1) The java.io package defines I/O in terms of streams, while the java.nio package defines I/O in terms of buffers and channels. The “n” in nio stands for “non-blocking”. The java.net package provides specific support for network I/O.

  The package java.io has two major parts: character streams and byte streamsCharacter streams deal with text-based I/O works, while character is 16-bit UTF-16 characters; byte streams handle data-based I/O works, whereas byte are 8 bits. The character streams are called writers and readers, while the byte streams are called input streams and output streams. So when we talk about Buffered byte streams we mean both BufferedInputStream and BufferedOutputStream; when we talk about Buffered character streams, we mean BufferedReader and BufferedWriter.

 

2) Byte streams defines basic byte input and output streams,  InputStream and OutputStream are the abstract superclass for such kind of streams.

  The abstract class InputStream declares methods to read bytes from a particular source. InputStream is the superclass of most byte input streams in java.io, and has the following methods:

public abstract int read() throws IOException

Reads a single byte of data and returns the byte that was read, as an integer in the range 0 to 255, not 128 to 127; in other words, the byte value is treated as unsigned. If no byte is available because the end of the stream has been reached, the value 1 is returned. This method blocks until input is available, the end of stream is found, or an exception is thrown. The read method returns an int instead of an actual byte value because it needs to return all valid byte values plus a flag value to indicate the end of stream. This requires more values than can fit in a byte and so the larger int is used.

public int read(byte[] buf, int offset, int count) throws IOException

Reads into a part of a byte array. The maximum number of bytes read is count. The bytes are stored from buf[offset] up to a maximum of buf[offset+count-1]all other values in buf are left unchanged. The number of bytes actually read is returned. If no bytes are read because the end of the stream was found, the value 1 is returned. If count is zero then no bytes are read and zero is returned. This method blocks until input is available, the end of stream is found, or an exception is thrown. If the first byte cannot be read for any reason other than reaching the end of the streamin particular, if the stream has already been closedan IOException is thrown. Once a byte has been read, any failure that occurs while trying to read subsequent bytes is not reported with an exception but is treated as encountering the end of the streamthe method completes normally and returns the number of bytes read before the failure occurred.

public int read(byte[] buf) throws IOException

Equivalent to read(buf,0, buf.length).

public long skip(long count) throws IOException

Skips as many as count bytes of input or until the end of the stream is found. Returns the actual number of bytes skipped. If count is negative, no bytes are skipped.

public int available() throws IOException

Returns the number of bytes that can be read (or skipped over) without blocking. The default implementation returns zero.

public void close() throws IOException

Closes the input stream. This method should be invoked to release any resources (such as file descriptors) associated with the stream. Once a stream has been closed, further operations on the stream will throw an IOException. Closing a previously closed stream has no effect. The default implementation of close does nothing.

  The implementation of InputStream requires only that a subclass provide the single-byte variant of read because the other read methods are defined in terms of this one. Most streams, however, can improve performance by overriding other methods as well. The default implementations of available and close will usually need to be overridden as appropriate for a particular stream.

 

  The abstract class OutputStream is analogous to InputStream; it provides an abstraction for writing bytes to a destination. Its methods are:

public abstract void write(int b) throws IOException

Writes b as a byte. The byte is passed as an int because it is often the result of an arithmetic operation on a byte. Expressions involving bytes are type int, so making the parameter an int means that the result can be passed without a cast to byte. Note, however, that only the lowest 8 bits of the integer are written. This method blocks until the byte is written.

public void write(byte[] buf, int offset, int count) tHRows IOException

Writes part of an array of bytes, starting at buf[offset] and writing count bytes. This method blocks until the bytes have been written.

public void write(byte[] buf) throws IOException

Equivalent to write(buf,0, buf.length).

public void flush() throws IOException

Flushes the stream. If the stream has buffered any bytes from the various write methods, flush writes them immediately to their destination. Then, if that destination is another stream, it is also flushed. One flush invocation will flush all the buffers in a chain of streams. If the stream is not buffered, flush may do nothingthe default implementation. This method is defined in the Flushable interface.

public void close() throws IOException

Closes the output stream. This method should be invoked to release any resources (such as file descriptors) associated with the stream. Once a stream has been closed, further operations on the stream will throw an IOException. Closing a previously closed stream has no effect.The default implementation of close does nothing.

  The implementation of OutputStream requires only that a subclass provide the single-byte variant of write because the other write methods are defined in terms of this one. Most streams, however, can improve performance by overriding other methods as well. The default implementations of flush and close will usually need to be overridden as appropriate for a particular streamin particular, buffered streams may need to flush when closed.

 

3) Reader and Writer are abstract classes for reading and writing streams of characters.

  The abstract class Reader provides a character stream analogous to the byte stream InputStream and the methods of Reader essentially mirror those of InputStream:

public int read() throws IOException

Reads a single character and returns it as an integer in the range 0 to 65535. If no character is available because the end of the stream has been reached, the value 1 is returned. This method blocks until input is available, the end of stream is found, or an exception is thrown.

public abstract int read(char[] buf, int offset, int count) throws IOException

Reads into a part of a char array. The maximum number of characters to read is count. The read characters are stored from buf[offset] up to a maximum of buf[offset+count-1]all other values in buf are left unchanged. The number of characters actually read is returned. If no characters are read because the end of the stream was found, 1 is returned. If count is zero then no characters are read and zero is returned. This method blocks until input is available, the end of stream is found, or an exception is thrown. If the first character cannot be read for any reason other than finding the end of the streamin particular, if the stream has already been closedan IOException is thrown. Once a character has been read, any failure that occurs while trying to read characters does not cause an exception, but is treated just like finding the end of the streamthe method completes normally and returns the number of characters read before the failure occurred.

public int read(char[] buf) throws IOException

Equivalent to read(buf,0, buf.length).

public int read(java.nio.CharBuffer buf) throws IOException

Attempts to read as many characters as possible into the specified character buffer, without overflowing it. The number of characters actually read is returned. If no characters are read because the end of the stream was found, 1 is returned. This is equivalent to reading into an array that has the same length as the buffer has available capacity, and then copying the array into the buffer. This method is defined in the java.lang.Readable interface, and has no counterpart in InputStream.

public long skip(long count) throws IOException

Skips as many as count characters of input or until the end of the stream is found. Returns the actual number of characters skipped. The value of count must not be negative.

public boolean ready() tHRows IOException

Returns TRue if the stream is ready to read; that is, there is at least one character available to be read. Note that a return value of false does not guarantee that the next invocation of read will block because data could have become available by the time the invocation occurs.

public abstract void close() throws IOException

Closes the stream. This method should be invoked to release any resources (such as file descriptors) associated with the stream. Once a stream has been closed, further operations on the stream will throw an IOException. Closing a previously closed stream has no effect.

  The implementation of Reader requires that a subclass provide an implementation of both the read method that reads into a char array, and the close method. Many subclasses will be able to improve performance if they also override some of the other methods.

 

  The abstract class Writer provides a stream analogous to OutputStream but designed for use with characters instead of bytes. The methods of Writer essentially mirror those of OutputStream, but add some other useful forms of write:

public void write(int ch) throws IOException

Writes ch as a character. The character is passed as an int but only the lowest 16 bits of the integer are written. This method blocks until the character is written.

public abstract void write(char[] buf, int offset, int count) throws IOException

Writes part of an array of characters, starting at buf[offset] and writing count characters. This method blocks until the characters have been written.

public void write(char[] buf) throws IOException

Equivalent to write(buf,0, buf.length).

public void write(String str, int offset, int count) throws IOException

Writes count characters from the string str onto the stream, starting with str.charAt(offset).

public void write(String str) throws IOException

Equivalent to write(str,0, str.length()).

public abstract void flush() throws IOException

Flushes the stream. If the stream has buffered any characters from the various write methods, flush immediately writes them to their destination. Then, if that destination is another stream, it is also flushed. One flush invocation will flush all the buffers in a chain of streams. If a stream is not buffered flush will do nothing.

public abstract void close() throws IOException

Closes the stream, flushing if necessary. This method should be invoked to release any resources (such as file descriptors) associated with the stream. Once a stream has been closed, further operations on the stream will throw an IOException. Closing a previously closed stream has no effect.

  Subclasses of Writer must implement the array writing variant of write, the close method, and the flush method. All other Writer methods are implemented in terms of these three.

 

  The standard streams System.in, System.err and System.out are byte streams instead of character streams(System.in is of type InputStream, System.out and System.err is of type PrintStream, which is subclass of FilterOutputStream, which extends OutputStream). You could take advantage of the InputStreamReader as a bridge to transform an byte stream to a character stream. PrintStream has been replaced by its equivalent character-based version PrintWriter. PrintWriter implements all of the print methods found in PrintStream. Generally, you should avoid creating PrintStream objects directly.

 

4) The conversion streams InputStreamReader and OutputStreamWriter translate between character and byte streams using either a specified character set encoding or the default encoding for the local system. InputStreamReader is a subclass of Reader, while OutputStreamWriter is a subclass of Writer. An InputStreamReader object is given a byte input stream as its source and produces the corresponding UTF-16 characters. An OutputStreamWriter object is given a byte output stream as its destination and produces encoded byte forms of the UTF-16 characters written on it.

  They can be represented by name or a Charset, or by a CharsetDecoder or CharsetEncoder object from the java.nio.charset package.

public InputStreamReader(InputStream in)

Creates an InputStreamReader to read from the given InputStream using the default character set encoding.

public InputStreamReader(InputStream in, Charset c)

Creates an InputStreamReader to read from the given InputStream using the given character set encoding.

public InputStreamReader(InputStream in, CharsetDecoder c)

Creates an InputStreamReader to read from the given InputStream using the given character set decoder.

public InputStreamReader(InputStream in, String enc) throws UnsupportedEncodingException

Creates an InputStreamReader to read from the given InputStream using the named character set encoding. If the named encoding is not supported an UnsupportedEncodingException is thrown.

public OutputStreamWriter(OutputStream out)

Creates an OutputStreamWriter to write to the given OutputStream using the default character set encoding.

public OutputStreamWriter(OutputStream out, Charset c)

Creates an OutputStreamWriter to write to the given OutputStream using the given character set encoding.

public OutputStreamWriter(OutputStream out, CharsetEncoder c)

Creates an OutputStreamWriter to write to the given OutputStream using the given character set encoder.

public OutputStreamWriter(OutputStream out, String enc) tHRows UnsupportedEncodingException

Creates an OutputStreamWriter to write to the given OutputStream using the named character set encoding. If the named encoding is not supported an UnsupportedEncodingException is thrown.

  The FileReader and FileWriter classes are subclasses of these conversion streams. This helps you read and write local files correctly in a consistent, Unicode-savvy fashion using the local encoding.

 

5) The java.io package defines several types of streams. The stream types usually have input/output pairs, and most have both byte stream and character stream variants. Some of these streams define general behavioral properties. For example:

  • Filter streams are abstract classes representing streams with some filtering operation applied as data is read or written by another stream. For example, a FilterReader object gets input from another Reader object, processes (filters) the characters in some manner, and returns the filtered result. You build sequences of filtered streams by chaining various filters into one large filter. Output can be filtered similarly.

  • Buffered streams add buffering so that read and write need not, for example, access the file system for every invocation. The character variants of these streams also add the notion of line-oriented text.

  • Piped streams are pairs such that, say, characters written to a PipedWriter can be read from a PipedReader.

  A group of streams, called in-memory streams, allow you to use in-memory data structures as the source or destination for a stream:

  • ByteArray streams use a byte array.

  • CharArray streams use a char array.

  • String streams use string types.

  The I/O package also has input and output streams that have no output or input counterpart:

  • The Print streams provide print and println methods for formatting printed data in human-readable text form.

  • LineNumberReader is a buffered reader that tracks the line numbers of the input (characters only).

  • SequenceInputStream converts a sequence of InputStream objects into a single InputStream so that a list of concatenated input streams can be treated as a single input stream (bytes only).

  There are also streams that are useful for building parsers:

  • Pushback streams add a pushback buffer you can use to put back data when you have read too far.

  • The StreamTokenizer class breaks a Reader into a stream of tokensrecognizable "words" that are often needed when parsing user input (characters only).

  These classes can be extended to create new kinds of stream classes for specific applications.

 

5.1) Synchronization of byte streams and character streams:

  Each byte stream class synchronizes on the current stream object when performing operations that must be free from interference. This allows multiple threads to use the same streams yet still get well-defined behavior when invoking individual stream methods.

  The character streams use a different synchronization strategy from the byte streams. The character streams synchronize on a protected lock field which, by default, is a reference to the stream object itself. However, both Reader and Writer provide a protected constructor that takes an object for lock to refer to. Some subclasses set the lock field to refer to a different object. For example, the StringWriter class that writes its character into a StringBuffer object sets its lock object to be the StringBuffer object. If you are writing a reader or writer, you should set the lock field to an appropriate object if this is not appropriate. Conversely, if you are extending an existing reader or writer you should always synchronize on lock and not this.

 

5.2) Filter streams:

  Filter streams FilterInputStream, FilterOutputStream, FilterReader, and FilterWriter help you chain streams to produce composite streams of greater utility.

  FilterInputStream contains some other input stream, which it uses as its basic source of data, possibly transforming the data along the way or providing additional functionality. The class FilterInputStreamitself simply overrides all methods of InputStream with versions that pass all requests to the contained input stream. Subclasses of FilterInputStream may further override some of these methods and may also provide additional methods and fields.

  FilterOutputStream is the superclass of all classes that filter output streams. These streams sit on top of an already existing output stream (the underlying output stream) which it uses as its basic sink of data, but possibly transforming the data along the way or providing additional functionality.

  FilterReader is an abstract class for reading filtered character streams. The abstract class FilterReader itself provides default methods that pass all requests to the contained stream. Subclasses of FilterReader should override some of these methods and may also provide additional methods and fields.

  FilterWriter is an abstract class for writing filtered character streams. The abstract class FilterWriter itself provides default methods that pass all requests to the contained stream. Subclasses of FilterWriter should override some of these methods and may also provide additional methods and fields.

  Here is an example of FilterReader which convert a string to the upper case:

import java.io.Reader;
import java.io.IOException;
import java.io.FilterReader;
import java.io.StringReader;

public class UpperCaseConverter extends FilterReader {

	protected UpperCaseConverter(Reader reader) {
		super(reader);
	}
	
	public int read() throws IOException {
		int ch = super.read();
		if(ch != -1) ch = (int)Character.toUpperCase((char)ch);
		return ch;
	}

	public static void main(String[] args) throws IOException {
		Reader reader = new UpperCaseConverter(new StringReader("JavaBeta"));
		int ch;
		while((ch = reader.read()) != -1) System.out.print((char)ch);
		System.out.println();
	}
}

Output:

JAVABETA

 

5.3) The Buffered stream classesBufferedInputStream, BufferedOutputStream, BufferedReader, and BufferedWriterbuffer their data to avoid every read or write going directly to the next stream. These classes are often used in conjunction with File streamsaccessing a disk file is much slower than using a memory buffer, and buffering helps reduce file accesses.

  BufferedInputStream extends FilterInputStream, which extends InputStream. BufferedInputStream adds functionality to another input stream-namely, the ability to buffer the input and to support the mark and reset methods. When the BufferedInputStream is created, an internal buffer array is created. As bytes from the stream are read or skipped, the internal buffer is refilled as necessary from the contained input stream, many bytes at a time. The mark operation remembers a point in the input stream and the reset operation causes all the bytes read since the most recent mark operation to be reread before new bytes are taken from the contained input stream.

  BufferedOutputStream extends FilterOutputStream, which extends  OutputStream. BufferedOutputStream implements a buffered output stream. By setting up such an output stream, an application can write bytes to the underlying output stream without necessarily causing a call to the underlying system for each byte written.

  BufferedReader extends Reader. BufferedReader reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines. The buffer size may be specified, or the default size may be used. The default is large enough for most purposes.

  BufferedWriter extends Writer. BufferedWriter writes text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings. The buffer size may be specified, or the default size may be accepted. The default is large enough for most purposes.

 

5.4) Pipes provide an I/O-based mechanism for communicating data between different threads. Piped streams PipedInputStream, PipedOutputStream, PipedReader, and PipedWriter are used as input/output pairs; data written on the output stream of a pair is the data read on the input stream. The pipe maintains an internal buffer with an implementation-defined capacity that allows writing and reading to proceed at different rates -- there is no way to control the size of the buffer.

  The only safe way to use Piped streams is with two threads: one for reading and one for writing. Writing on one end of the pipe blocks the thread when the pipe fills up. If the writer and reader are the same thread, that thread will block permanently. Reading from a pipe blocks the thread if no input is available.

 

   PipedInputStream extends InputStream. A piped input stream should be connected to a piped output stream; the piped input stream then provides whatever data bytes are written to the piped output stream. Typically, data is read from aPipedInputStream object by one thread and data is written to the corresponding PipedOutputStream by some other thread. Attempting to use both objects from a single thread is not recommended, as it may deadlock the thread. The piped input stream contains a buffer, decoupling read operations from write operations, within limits. A pipe is said to be broken if a thread that was providing data bytes to the connected piped output stream is no longer alive.

  PipedOutputStream extends OutputStream. A piped output stream can be connected to a piped input stream to create a communications pipe. The piped output stream is the sending end of the pipe. Typically, data is written to a PipedOutputStream object by one thread and data is read from the connected PipedInputStream by some other thread. Attempting to use both objects from a single thread is not recommended as it may deadlock the thread. The pipe is said to be broken if a thread that was reading data bytes from the connected piped input stream is no longer alive.

 PipedReader extends Reader. Piped character-input streams.

 PipedWriter extends Writer. Piped character-output streams.

Example:

import java.lang.Thread;
import java.lang.Runnable;
import java.io.Writer;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.IOException;

class WriterThread implements Runnable {
	private Writer out;
	
	WriterThread(Writer out) {
		this.out = out;
	}
	
	public void run() {
		try{
			for(char ch = 'a'; ch <= 'z'; ++ch) out.write(ch);
			out.close();
		} catch(IOException e) {
			System.out.println(e);
		}
	}
}


public class PipedTest {

	public static void main(String[] args) throws IOException {
		PipedReader reader = new PipedReader();
		PipedWriter writer = new PipedWriter();
		reader.connect(writer);
		
		Thread writer_thread = new Thread(new WriterThread(writer));
		writer_thread.start();
		
		int ch;
		while((ch = reader.read()) != -1) System.out.print((char)ch);
		System.out.println();
	}
}

Output:

abcdefghijklmnopqrstuvwxyz

 

5.5) ByteArrayInputStream extends InputStream. A ByteArrayInputStream contains an internal buffer that contains bytes that may be read from the stream. An internal counter keeps track of the next byte to be supplied by the read method. Closing a ByteArrayInputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.

  ByteArrayOutputStream extends OutputStream. This class implements an output stream in which the data is written into a byte array. The buffer automatically grows as data is written to it. The data can be retrieved using toByteArray() and toString(). Closing a ByteArrayOutputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.

Example:

import java.io.ByteArrayOutputStream;

public class ByteArrayTest {

	public static void main(String[] args) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		for(char ch = 'a'; ch <= 'z'; ++ch) out.write(ch);
		
		byte[] buf = out.toByteArray();
		for(int i = 0; i < buf.length; ++i) System.out.print((char)buf[i]);
		System.out.println();
	}
}

Output:

abcdefghijklmnopqrstuvwxyz

 

5.6) CharArrayReader extends Reader. This class implements a character buffer that can be used as a character-input stream.

  CharArrayWriter extends Writer. This class implements a character buffer that can be used as an Writer. The buffer automatically grows when data is written to the stream. The data can be retrieved using toCharArray() and toString(). Note: Invoking close() on this class has no effect, and methods of this class can be called after the stream has closed without generating an IOException.

Example:

import java.io.CharArrayReader;
import java.io.IOException;

public class CharArrayTest{

	public static void main(String[] args) throws IOException {
		char[] buf = new char[26];
		for(int i = 0; i < 26; ++i) buf[i] = (char)('a' + i);
		CharArrayReader in = new CharArrayReader(buf);
		
		int ch;
		while((ch = in.read()) != -1) System.out.print((char)ch);
		System.out.println();
	}
}

Output:

abcdefghijklmnopqrstuvwxyz

 

5.7) StringReader extends Reader, and it defines a character stream whose source is a string.

StringWriter extends Writer, and it defines a character stream that collects its output in a string buffer, which can then be used to construct a string. Closing a StringWriter has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.

Example:

import java.io.StringReader;
import java.io.IOException;

public class StringStreamTest {

	public static void main(String[] args) throws IOException {
		String buf = "JavaBeta";
		StringReader reader = new StringReader(buf);
		int ch;
		while((ch = reader.read()) != -1) System.out.print((char)ch);
		System.out.println();
	}
}

 

Output:

JavaBeta

 

5.8) The Print streamsPrintStream and PrintWriter provide methods that make it easy to write the values of primitive types and objects to a stream, in a human-readable text formatas.

  The PrintStream class acts on byte streams while the PrintWriter class acts on character streams. Because printing is clearly character-related output, the PrintWriter class is the class you should use. However, for historical reasons System.out and System.err are PrintStreams that use the default character set encodingthese are the only PrintStream objects you should use.

  PrintWriter has eight constructors.

public PrintWriter(Writer out, boolean autoflush)

Creates a new PrintWriter that will write to the stream out. If autoflush is true, println invokes flush. Otherwise, println invocations are treated like any other method, and flush is not invoked. Autoflush behavior cannot be changed after the stream is constructed.

public PrintWriter(Writer out)

Equivalent to PrintWriter(out,false) .

public PrintWriter(OutputStream out, boolean autoflush)

Equivalent to PrintWriter(new OutputStreamWriter(out), autoflush).

public PrintWriter(OutputStream out)

Equivalent to PrintWriter(newOutputStreamWriter(out), false).

public PrintWriter(File file) throws FileNotFoundException

Equivalent to PrintWriter(newOutputStreamWriter(fos)) , where fos is a FileOutputStream created with the given file.

public PrintWriter(File file, String enc) throws FileNotFoundException, UnsupportedEncodingException

Equivalent to PrintWriter(newOutputStreamWriter(fos, enc)), where fos is a FileOutputStream created with the given file.

public PrintWriter(String filename) throws FileNotFoundException

Equivalent to PrintWriter(newOutputStreamWriter(fos)) , where fos is a FileOutputStream created with the given file name.

public PrintWriter(String filename, String enc) throws FileNotFoundException, UnsupportedEncodingException

Equivalent to PrintWriter(newOutputStreamWriter(fos, enc)), where fos is a FileOutputStream created with the given file name.

 

5.9) LineNumberReader extends BuffredReader, which extends Reader. LineNumberReader defines a buffered character-input stream that keeps track of line numbers. This class defines methods setLineNumber(int) and getLineNumber() for setting and getting the current line number respectively.

  By default, line numbering begins at 0. This number increments at every line terminator as the data is read, and can be changed with a call to setLineNumber(int). Note however, that setLineNumber(int) does not actually change the current position in the stream; it only changes the value that will be returned by getLineNumber().

  A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.

Example:

import java.io.FileReader;
import java.io.LineNumberReader;
import java.io.IOException;

public class LineNumberReaderTest {

	public static void main(String[] args) throws IOException {
		FileReader fileReader = new FileReader("./Chapter 20/section5/LineNumberReaderTest.java");
		LineNumberReader reader = new LineNumberReader(fileReader);
		int ch;
		char flag = 'I';
		while((ch = reader.read()) != -1){
			if(((char)ch) == flag ){
				System.out.println(flag + " at line " + reader.getLineNumber() + ".");
				return;
			}
		}
		
		System.out.println(flag + "not found.");
	}
}

Output:

I at line 4.

 

Note that the corresponding byte stream version LineNumberInputStream is deprecated, and you should NOT USE IT.

 

5.10) SequenceInputStream extends InputStream. A SequenceInputStream represents the logical concatenation of other input streams. It starts out with an ordered collection of input streams and reads from the first one until end of file is reached, whereupon it reads from the second one, and so on, until end of file is reached on the last of the contained input streams.

Constructors:

public SequenceInputStream(Enumeration<? extends InputStream> e)

  Initializes a newly created SequenceInputStream by remembering the argument, which must be an Enumeration that produces objects whose run-time type is InputStream. The input streams that are produced by the enumeration will be read, in order, to provide the bytes to be read from this SequenceInputStream. After each input stream from the enumeration is exhausted, it is closed by calling itsclose method.

public SequenceInputStream(InputStream s1,
                   InputStream s2)

  Initializes a newly created SequenceInputStream by remembering the two arguments, which will be read in order, first s1 and then s2, to provide the bytes to be read from this SequenceInputStream.

 

Example:

import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.io.SequenceInputStream;

public class SequenceInputStreamTest {

	public static void main(String[] args) throws IOException, FileNotFoundException {
		int n = 3;
		String file = "./files/file ";
		// use buffered input and output stream to increase efficiency
		OutputStream out = new BufferedOutputStream(new FileOutputStream("./files/file.txt"));
		List<InputStream> list = new ArrayList<InputStream>(n);
		for(int i = 1; i <= n; ++i) {
			list.add(new BufferedInputStream(new FileInputStream(file + String.valueOf(i) + ".txt")));
		}
		
		Enumeration<InputStream> files = Collections.enumeration(list);
		InputStream in = new SequenceInputStream(files);
		int ch;
		while((ch = in.read()) != -1) out.write(ch);
		
		out.flush();
		
		in.close();
		out.close();
	}
}

Input:

file 1.txt: Initializes a newly created SequenceInputStream by remembering the argument, which must be an Enumeration that produces objects whose run-time type is InputStream.

file 2.txt: The input streams that are produced by the enumeration will be read, in order, to provide the bytes to be read from this SequenceInputStream.

file 3.txt: After each input stream from the enumeration is exhausted, it is closed by calling its close method.

Output:

file.txt: Initializes a newly created SequenceInputStream by remembering the argument, which must be an Enumeration that produces objects whose run-time type is InputStream. The input streams that are produced by the enumeration will be read, in order, to provide the bytes to be read from this SequenceInputStream. After each input stream from the enumeration is exhausted, it is closed by calling its close method.

 

5.11) A Pushback stream lets you push back, or "unread," characters or bytes when you have read too far. Pushback is typically useful for breaking input into tokens.

  PushbackInputStream extends FilterInputStream, which is a subclass of InputStream. A PushbackInputStream adds functionality to another input stream, namely the ability to "push back" or "unread" one byte. This is useful in situations where it is convenient for a fragment of code to read an indefinite number of data bytes that are delimited by a particular byte value; after reading the terminating byte, the code fragment can "unread" it, so that the next read operation on the input stream will reread the byte that was pushed back. For example, bytes representing the characters constituting an identifier might be terminated by a byte representing an operator character; a method whose job is to read just an identifier can read until it sees the operator and then push the operator back to be re-read.

  PushbackReader extends FilterReader, which is a subclass of Reader. A character-stream reader that allows characters to be pushed back into the stream.

  PushbackReader has two constructors:

PushbackReader(Reader in)

Creates a new pushback reader with a one-character pushback buffer.

PushbackReader(Reader in, int size)

Creates a new pushback reader with a pushback buffer of the given size.

The characteristic method of PushbackReader is unread:

public void unread(int c) throws IOException

Pushes back a single character by copying it to the front of the pushback buffer. After this method returns, the next character to be read will have the value (char)c.

Parameters:
c - The int value representing a character to be pushed back
Throws:
IOException - If the pushback buffer is full, or if some other I/O error occurs
 
public void unread(char[] cbuf,
          int off,
          int len)
            throws IOException

Pushes back a portion of an array of characters by copying it to the front of the pushback buffer. After this method returns, the next character to be read will have the value cbuf[off], the character after that will have the value cbuf[off+1], and so forth.

Parameters:
cbuf - Character array
off - Offset of first character to push back
len - Number of characters to push back
Throws:
IOException - If there is insufficient room in the pushback buffer, or if some other I/O error occurs
 
public void unread(char[] cbuf) throws IOException

Pushes back an array of characters by copying it to the front of the pushback buffer. After this method returns, the next character to be read will have the value cbuf[0], the character after that will have the value cbuf[1], and so forth.

Parameters:
cbuf - Character array to push back
Throws:
IOException - If there is insufficient room in the pushback buffer, or if some other I/O error occurs

 

6) The DataOutput interface provides for converting data from any of the Java primitive types to a series of bytes and writing these bytes to a binary stream. There is also a facility for converting a String into modified UTF-8 format and writing the resulting series of bytes. For all the methods in this interface that write bytes, it is generally true that if a byte cannot be written for any reason, an IOException is thrown.

  The DataInput interface provides for reading bytes from a binary stream and reconstructing from them data in any of the Java primitive types. There is also a facility for reconstructing a String from data in modified UTF-8 format. It is generally true of all the reading routines in this interface that if end of file is reached before the desired number of bytes has been read, an EOFException (which is a kind of IOException) is thrown. If any byte cannot be read for any reason other than end of file, an IOException other than EOFException is thrown. In particular, an IOException may be thrown if the input stream has been closed.

  The DataInputStream class extends FilterInputStream, which is a subclass of Inputstream, and implements the DataInput interface. A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way. An application uses a data output stream to write data that can later be read by a data input stream.

  The DataOutputStream class extends FilterOutputStream, which is a subclass of OutputStream, and implements the DataOutput interface. A data output stream lets an application write primitive Java data types to an output stream in a portable way. An application can then use a data input stream to read the data back in.

Example:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;

public class DataStreamTest {

	public static void main(String[] args) throws IOException, FileNotFoundException {
		int a = 100;
		char b = 'a';
		boolean c = false;
		double d = 2.5;
		String e = "JavaBeta";
		
		DataOutputStream out = new DataOutputStream(new FileOutputStream("./files/data.dat"));
		out.writeInt(a);
		out.writeChar(b);
		out.writeBoolean(c);
		out.writeDouble(d);
		out.writeUTF(e);
		out.close();
		
		DataInputStream in = new DataInputStream(new FileInputStream("./files/data.dat"));
		int ia = in.readInt();
		char ib = in.readChar();
		boolean ic = in.readBoolean();
		double id = in.readDouble();
		String ie = in.readUTF();
		in.close();
		
		System.out.println(ia);
		System.out.println(ib);
		System.out.println(ic);
		System.out.println(id);
		System.out.println(ie);
	}
}

Output:

100
a
false
2.5
JavaBeta

 

The data.dat File content(human-unreadable, binary code):

QQ截圖20140313103522

 

7) The File streams -- FileInputStream, FileOutputStream, FileReader, and FileWriter -- allow you to treat a file as a stream for input or output. Each type is instantiated with one of three constructors:

  • A constructor that takes a String that is the name of the file.

  • A constructor that takes a File object that refers to the file

  • A constructor that takes a FileDescriptor object (see below).

  The RandomAccessFile class provides a more sophisticated file mechanism than the File streams do. A random access file behaves like a large array of bytes stored in the file system. There is a kind of cursor, or index into the implied array, called the file pointer; input operations read bytes starting at the file pointer and advance the file pointer past the bytes read. If the random access file is created in read/write mode, then output operations are also available; output operations write bytes starting at the file pointer and advance the file pointer past the bytes written.

  The FilenameFilter interface provides objects that filter unwanted files from a list. It supports a single method:

boolean accept(File dir, String name)

Returns true if the file named name in the directory dir should be part of the filtered output.

 

8) The process of converting an object's representation into a stream of bytes is known as serialization, while reconstituting an object from a byte stream is deserialization.

  The Object streams ObjectInputStream and ObjectOutputStream allow you to read and write object graphs in addition to the well-known types (primitives, strings, and arrays). By "object graph" we mean that when you use writeObject to write an object to an ObjectOutputStream, bytes representing the object -- including all other objects that it referencesare written to the stream. This process of transforming an object into a stream of bytes is called serialization.

  When an ObjectOutputStream writes a serialized object, the object must implement the Serializable marker interface. Being serializable can be quite simple. The default serialization process is to serialize each field of the object that is neither Transient nor static. Primitive types and strings are written in the same encoding used by DataOutputStream; objects are serialized by calling writeObject. With default serialization, all serialized fields that are object references must refer to serializable object types. Default serialization also requires either that your superclass have a no-arg constructor (so that deserialization can invoke it) or that it also be Serializable (in which case declaring your class to implement Serializable is redundant but harmless).

  Objects are serialized and deserialized down the type treefrom the highest-level class that is Serializable to the most specific class. This order is rarely important when you're serializing, but it can be important when you're deserializing.

  The Externalizable interface extends Serializable. A class that implements Externalizable takes complete control over its serialized state, assuming responsibility for all the data of its superclasses, any versioning issues, and so on.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章