Java ScreenShot
     

Screenshot Core Java 2: Volume I - Fundamentals

Table of Contents
 12.  Streams and Files


Streams

Input/output techniques are not particularly exciting, but without the ability to read and write data, your programs are severely limited. This chapter is about how to get input from any source of data that can send out a sequence of bytes and how to send output to any destination that can receive a sequence of bytes. These sources and destinations of byte sequences can be—and often are—files, but they can also be network connections and even blocks of memory. There is a nice payback to keeping this generality in mind: for example, information stored in files and information retrieved from a network connection is handled in essentially the same way. (See Volume 2 for more information about coding with networks.) Of course, while data is always ultimately stored as a sequence of bytes, it is often more convenient to think of it as having some higher-level structure such as being a sequence of characters or objects. For that reason, we dispense with low-level input/output quickly and focus on higher level facilities for the majority of the chapter. In Java, an object from which we can read a sequence of bytes is called an input stream. An object to which we can write a sequence of bytes is called an output stream. These are specified in the abstract classes InputStream and OutputStream. Since byte-oriented streams are inconvenient for processing information stored in Unicode (recall that Unicode uses two bytes per character), there is a separate hierarchy of classes for processing Unicode characters that inherit from the abstract Reader and Writer classes. These classes have read and write operations that are based on 2-byte Unicode characters rather than on single-byte characters. You saw abstract classes in . Recall that the point of an abstract class is to provide a mechanism for factoring out the common behavior of classes to a higher level. This leads to cleaner code and makes the inheritance tree easier to understand. The same game is at work with input and output in the Java coding language. As you will soon see, Java derives from these four abstract classes a zoo of concrete classes. You can visit almost any conceivable input/output creature in this zoo.

Reading and Writing Bytes

The InputStream class has an abstract method:

abstract int read()


This method reads one byte and returns the byte that was read, or –1 if it encounters the end of the input source. The designer of a concrete input stream class overrides this method to provide useful functionality. For example, in the FileInputStream class, this method reads one byte from a file. System.in is a predefined object of a subclass of InputStream that allows you to read information from the keyboard. The InputStream class also has nonabstract methods to read an array of bytes or to skip a number of bytes. These methods call the abstract read method, so that subclasses need to override only one method. Similarly, the OutputStream class defines the abstract method

abstract void write(int b)


which writes one byte to an output location. Both the read and write methods can block a thread until the byte is actually read or written. This means that if the stream cannot immediately be read from or written to (usually because of a busy network connection), Java suspends the thread containing this call. This gives other threads the chance to do useful work while the method is waiting for the stream to again become available. (We discuss threads in depth in Volume 2.) The available method lets you check the number of bytes that are currently available for reading. This means a fragment like the following is unlikely to ever block:

int bytesAvailable = System.in.available();
if (bytesAvailable > 0)
{
 byte[] data = new byte[bytesAvailable];
 System.in.read(data);
}


When you have finished reading or writing to a stream, close it by calling the close method. This call frees up operating system resources that are in limited supply. If an app opens too many streams without closing them, system resources may become depleted. Closing an output stream also flushes the buffer used for the output stream: any characters that were temporarily placed in a buffer so that they could be delivered as a larger packet are sent off. In particular, if you do not close a file, the last packet of bytes may never be delivered. You can also manually flush the output with the flush method. Even if a stream class provides concrete methods to work with the raw read and write functions, Java programmers rarely use them because programs rarely need to read and write streams of bytes. The data that you are interested in probably contain numbers, strings, and objects. Java gives you many stream classes derived from the basic InputStream and OutputStream classes that let you work with data in the forms that you usually use rather than at the low, byte level.

java.io.InputStream 1.0

Java graphics api_icon.gif
  • abstract int read()

    reads a byte of data and returns the byte read. The read method returns a –1 at the end of the stream.

  • int read(byte[] b)

    reads into an array of bytes and returns the actual number of bytes read, or –1 at the end of the stream. The read method reads at most b.length bytes.

  • int read(byte[] b, int off, int len)

    reads into an array of bytes. The read method returns the actual number of bytes read, or –1 at the end of the stream.

    Parameters:

    b

    The array into which the data is read

     

    off

    The offset into b where the first bytes should be placed

     

    len

    The maximum number of bytes to read

  • long skip(long n)

    skips n bytes in the input stream. It returns the actual number of bytes skipped (which may be less than n if the end of the stream was encountered).

  • int available()

    returns the number of bytes available without blocking. (Recall that blocking means that the current thread loses its turn.)

  • void close()

    closes the input stream.

  • void mark(int readlimit)

    puts a marker at the current position in the input stream. (Not all streams support this feature.) If more than readlimit bytes have been read from the input stream, then the stream is allowed to forget the marker.

  • void reset()

    returns to the last marker. Subsequent calls to read reread the bytes. If there is no current marker, then the stream is not reset.

  • boolean markSupported()

    returns true if the stream supports marking.

java.io.OutputStream 1.0

Java graphics api_icon.gif
  • abstract void write(int n)

    writes a byte of data.

  • void write(byte[] b)

    writes all bytes in the array b.

  • void write(byte[] b, int off, int len)

    Parameters:

    b

    The array from which to write the data

     

    off

    The offset into b to the first byte that will be written

     

    len

    The number of bytes to write

  • void close()

    flushes and closes the output stream.

  • void flush()

    flushes the output stream, that is, sends any buffered data to its destination.

Screenshot

Java ScreenShot
     
Top
 

Comments