Home | | Web Programming | The Byte Streams - java.io

Chapter: Java The Complete Reference : The Java Library : Input/Output: Exploring java.io

The Byte Streams - java.io

The byte stream classes provide a rich environment for handling byte-oriented I/O. A byte stream can be used with any type of object, including binary data.

The Byte Streams

 

The byte stream classes provide a rich environment for handling byte-oriented I/O. A byte stream can be used with any type of object, including binary data. This versatility makes byte streams important to many types of programs. Since the byte stream classes are topped by InputStream and OutputStream, our discussion begins with them.

 

InputStream

 

InputStream is an abstract class that defines Java’s model of streaming byte input. It implements the AutoCloseable and Closeableinterfaces. Most of the methods in this class will throw an IOException when an I/O error occurs. (The exceptions are mark( ) andmarkSupported( ).) Table 20-1 shows the methods in InputStream.

 

OutputStream

 

OutputStream is an abstract class that defines streaming byte output. It implements the AutoCloseable, Closeable, and Flushableinterfaces. Most of the methods defined by this class return void and throw an IOException in the case of I/O errors. Table 20-2 shows the methods in OutputStream.

 




FileInputStream

 

The FileInputStream class creates an InputStream that you can use to read bytes from a file. Two commonly used constructors are shown here:

 

FileInputStream(String filePath) FileInputStream(File fileObj)

 

Either can throw a FileNotFoundException. Here, filePath is the full path name of a file, and fileObj is a File object that describes the file.

The following example creates two FileInputStreams that use the same disk file and each of the two constructors:

 

FileInputStream f0 = new FileInputStream("/autoexec.bat")

 

File f = new File("/autoexec.bat");

 

FileInputStream f1 = new FileInputStream(f);

 

Although the first constructor is probably more commonly used, the second allows you to closely examine the file using the Filemethods, before attaching it to an input stream. When a FileInputStream is created, it is also opened for reading. FileInputStreamoverrides six of the methods in the abstract class InputStream. The mark( ) and reset( ) methods are not overridden, and any attempt to use reset( ) on a FileInputStream will generate an

 

IOException.

 

The next example shows how to read a single byte, an array of bytes, and a subrange of an array of bytes. It also illustrates how to use available( ) to determine the number of bytes remaining and how to use the skip( ) method to skip over unwanted bytes. The program reads its own source file, which must be in the current directory. Notice that it uses the try-with-resources statement to automatically close the file when it is no longer needed.

 

    Demonstrate FileInputStream.

 

    This program uses try-with-resources. It requires JDK 7 or later.

 

    import java.io.*;

 

class FileInputStreamDemo {

 

public static void main(String args[]) { int size;

 

// Use try-with-resources to close the stream.

try ( FileInputStream f =

 

new FileInputStream("FileInputStreamDemo.java") ) {

 

System.out.println("Total Available Bytes: " +

 

(size = f.available()));

 

int n = size/40; System.out.println("First " + n + " bytes of the file one read() at a time");

for (int i=0; i < n; i++) {

 

System.out.print((char) f.read());

 

}

 

System.out.println("\nStill Available: " + f.available());

 

System.out.println("Reading the next " + n + " with one read(b[])");

 

byte b[] = new byte[n]; if (f.read(b) != n) {

System.err.println("couldn’t read " + n + " bytes.");

 

}

 

System.out.println(new String(b, 0, n));

System.out.println("\nStill Available: " + (size = f.available())); System.out.println("Skipping half of remaining bytes with skip()");

f.skip(size/2);

 

System.out.println("Still Available: " + f.available());

 

System.out.println("Reading " + n/2 + " into the end of array");

if (f.read(b, n/2, n/2) != n/2) {

 

System.err.println("couldn’t read " + n/2 + " bytes.");

 

}

 

System.out.println(new String(b, 0, b.length)); System.out.println("\nStill Available: " + f.available());

 

} catch(IOException e) { System.out.println("I/O Error: " + e);

}

 

}

 

}

Here is the output produced by this program:

 

Total Available Bytes: 1785

 

First 44 bytes of the file one read() at a time

 

   Demonstrate FileInputStream.

 

This pr

 

Reading the next 44 with one read(b[])

 

ogram uses try-with-resources. It requires J

 

Still Available: 1697

 

Skipping half of remaining bytes with skip() Still Available: 849

 

Reading 22 into the end of array ogram uses try-with-rebyte[n];

if (

 

Still Available: 827

 

This somewhat contrived example demonstrates how to read three ways, to skip input, and to inspect the amount of data available on a stream.

 

FileOutputStream

 

FileOutputStream creates an OutputStream that you can use to write bytes to a file. It implements the AutoCloseableCloseable, and Flushable interfaces. Four of its constructors are shown here:

 

FileOutputStream(String filePath) FileOutputStream(File fileObj) FileOutputStream(String filePath, boolean append) FileOutputStream(File fileObj, boolean append)

 

They can throw a FileNotFoundException. Here, filePath is the full path name of a file, and fileObj is a File object that describes the file. If append is true, the file is opened in append mode.

 

Creation of a FileOutputStream is not dependent on the file already existing. FileOutputStream will create the file before opening it for output when you create the object. In the case where you attempt to open a read-only file, an exception will be thrown.

The following example creates a sample buffer of bytes by first making a String and then using the getBytes( ) method to extract the byte array equivalent. It then creates three files. The first, file1.txt, will contain every other byte from the sample. The second,file2.txt, will contain the entire set of bytes. The third and last, file3.txt, will contain only the last quarter.

 

 

    Demonstrate FileOutputStream.

 

    //This program uses the traditional approach to closing a file.

 

import java.io.*;

 

class FileOutputStreamDemo {

 

public static void main(String args[]) {

 

String source = "Now is the time for all good men\n"

 

    " to come to the aid of their country\n"

    " and pay their due taxes.";

byte buf[] = source.getBytes(); FileOutputStream f0 = null; FileOutputStream f1 = null; FileOutputStream f2 = null;

 

try {   

f0     = new  FileOutputStream("file1.txt");

f1     = new  FileOutputStream("file2.txt");

f2     = new  FileOutputStream("file3.txt");

// write to first file

for (int i=0; i < buf.length; i += 2) f0.write(buf[i]);

    write to second file f1.write(buf);

 

    //write to third file

 

f2.write(buf, buf.length-buf.length/4, buf.length/4);

 

} catch(IOException e) { System.out.println("An I/O Error Occurred");

 

} finally { try {

 

if(f0 != null) f0.close(); } catch(IOException e) {

System.out.println("Error Closing file1.txt");

 

}

 

try {

 

if(f1 != null) f1.close();

 

} catch(IOException e) { System.out.println("Error Closing file2.txt");

}

 

try {

 

if(f2 != null) f2.close();

 

} catch(IOException e) { System.out.println("Error Closing file3.txt");

}

 

}

 

}

 

}

 

Here are the contents of each file after running this program. First, file1.txt:

 

Nwi h iefralgo e

 

t oet h i ftercuty n a hi u ae.

 

Next, file2.txt:

 

Now is the time for all good men

 

to come to the aid of their country and pay their due taxes.

 

Finally, file3.txt:

nd pay their due taxes.

As the comment at the top of the program states, the preceding program shows an example that uses the traditional approach to closing a file when it is no longer needed. This approach is required by all versions of Java prior to JDK 7 and is widely used in legacy code. As you can see, quite a bit of rather awkward code is required to explicitly call close( ) because each call could generate an IOException if the close operation fails. This program can be substantially improved by using the new try-with-resources statement. For comparison, here is the revised version. Notice that it is much shorter and streamlined:

 

    //Demonstrate FileOutputStream.

 

    //This version uses try-with-resources. It requires JDK 7 or later.

 

import java.io.*;

 

class FileOutputStreamDemo {

 

public static void main(String args[]) {

 

String source = "Now is the time for all good men\n"

 

    " to come to the aid of their country\n"

 

    " and pay their due taxes.";

 

byte buf[] = source.getBytes();

 

// Use try-with-resources to close the files.

 

try (FileOutputStream f0 = new FileOutputStream("file1.txt"); FileOutputStream f1 = new FileOutputStream("file2.txt"); FileOutputStream f2 = new FileOutputStream("file3.txt") )

 

{

 

// write to first file

 

for (int i=0; i < buf.length; i += 2) f0.write(buf[i]);

 

    //write to second file

    f1.write(buf);

 

    //write to third file

 

f2.write(buf, buf.length-buf.length/4, buf.length/4);

 

} catch(IOException e) { System.out.println("An I/O Error Occurred");

}

 

}

 

}

 

ByteArrayInputStream

 

ByteArrayInputStream is an implementation of an input stream that uses a byte array as the source. This class has two constructors, each of which requires a byte array to provide the data source:

 

ByteArrayInputStream(byte array [ ]) ByteArrayInputStream(byte array [ ], int start, int numBytes)

 

Here, array is the input source. The second constructor creates an InputStream from a subset of the byte array that begins with the character at the index specified by start and is numBytes long.

The close( ) method has no effect on a ByteArrayInputStream. Therefore, it is not necessary to call close( ) on aByteArrayInputStream, but doing so is not an error.

The following example creates a pair of ByteArrayInputStreams, initializing them with the byte representation of the alphabet:

 

// Demonstrate ByteArrayInputStream.

import java.io.*;

 

class ByteArrayInputStreamDemo {

 

public static void main(String args[]) {

String tmp = "abcdefghijklmnopqrstuvwxyz"; byte b[] = tmp.getBytes();

 

ByteArrayInputStream input1 = new ByteArrayInputStream(b); ByteArrayInputStream input2 = new ByteArrayInputStream(b,0,3);

 

}

 

}

 

The input1 object contains the entire lowercase alphabet, whereas input2 contains only the first three letters.

ByteArrayInputStream implements both mark( ) and reset( ). However, if mark( ) has not been called, then reset( ) sets the stream pointer to the start of the stream—which, in this case, is the start of the byte array passed to the constructor. The next example shows how to use the reset( ) method to read the same input twice. In this case, the program reads and prints the letters "abc" once in lowercase and then again in uppercase.

 

import java.io.*;

 

class ByteArrayInputStreamReset {

 

public static void main(String args[]) { String tmp = "abc";

 

byte b[] = tmp.getBytes();

 

ByteArrayInputStream in = new ByteArrayInputStream(b);

 

for (int i=0; i<2; i++) { int c;

 

while ((c = in.read()) != -1) { if (i == 0) {

 

System.out.print((char) c);

 

} else { System.out.print(Character.toUpperCase((char) c));

}

 

}

 

System.out.println();

 

in.reset();

 

}

 

}

 

}

 

This example first reads each character from the stream and prints it as-is in lowercase. It then resets the stream and begins reading again, this time converting each character to uppercase before printing. Here’s the output:

abc

ABC

 

 

 

ByteArrayOutputStream

 

ByteArrayOutputStream is an implementation of an output stream that uses a byte array as the destination.ByteArrayOutputStream has two constructors, shown here:

 

ByteArrayOutputStream( ) ByteArrayOutputStream(int numBytes)

 

In the first form, a buffer of 32 bytes is created. In the second, a buffer is created with a size equal to that specified by numBytes. The buffer is held in the protected buf field of ByteArrayOutputStream. The buffer size will be increased automatically, if needed. The number of bytes held by the buffer is contained in the protected count field of ByteArrayOutputStream.

 

    Demonstrate ByteArrayOutputStream.

 

    //This program uses try-with-resources. It requires JDK 7 or later.

 

import java.io.*;

 

class ByteArrayOutputStreamDemo {

 

public static void main(String args[]) {

ByteArrayOutputStream f = new ByteArrayOutputStream();

String s = "This should end up in the array";

 

byte buf[] = s.getBytes();

 

try { f.write(buf);

 

} catch(IOException e) { System.out.println("Error Writing to Buffer"); return;

 

}

 

System.out.println("Buffer as a string");

System.out.println(f.toString());

 System.out.println("Into array");

 

byte b[] = f.toByteArray();

 

for (int i=0; i<b.length; i++) System.out.print((char) b[i]);

System.out.println("\nTo an OutputStream()");

 

// Use try-with-resources to manage the file stream.

 

try ( FileOutputStream f2 = new FileOutputStream("test.txt") )

 

{

 

f.writeTo(f2);

 

} catch(IOException e) { System.out.println("I/O Error: " + e); return;

 

}

System.out.println("Doing a reset"); f.reset();

 

for (int i=0; i\<3; i++) f.write('X');

 

System.out.println(f.toString());

 

}

 

}

 

When you run the program, you will create the following output. Notice how after the call to reset( ), the three X’s end up at the beginning.

 

Buffer as a string

 

This should end up in the array

 

Into array

 

This should end up in the array

 

To an OutputStream()

 

Doing a reset

 

XXX

 

This example uses the writeTo( ) convenience method to write the contents of f to test.txt. Examining the contents of the test.txt file created in the preceding example shows the result we expected:

 

This should end up in the array

 

Filtered Byte Streams

 

Filtered streams are simply wrappers around underlying input or output streams that transparently provide some extended level of functionality. These streams are typically accessed by methods that are expecting a generic stream, which is a superclass of the filtered streams. Typical extensions are buffering, character translation, and raw data translation. The filtered byte streams areFilterInputStream and FilterOutputStream. Their constructors are shown here:

 

FilterOutputStream(OutputStream os) FilterInputStream(InputStream is)

 

The methods provided in these classes are identical to those in InputStream and

 

OutputStream.

 

Buffered Byte Streams

 

For the byte-oriented streams, a buffered stream extends a filtered stream class by attaching a memory buffer to the I/O stream. This buffer allows Java to do I/O operations on more than a byte at a time, thereby improving performance. Because the buffer is available, skipping, marking, and resetting of the stream become possible. The buffered byte stream classes areBufferedInputStream and BufferedOutputStreamPushbackInputStream also implements a buffered stream.

BufferedInputStream

 

Buffering I/O is a very common performance optimization. Java’s BufferedInputStream class allows you to "wrap" anyInputStream into a buffered stream to improve performance.

BufferedInputStream has two constructors:

 

BufferedInputStream(InputStream inputStream) BufferedInputStream(InputStream inputStream, int bufSize)

 

The first form creates a buffered stream using a default buffer size. In the second, the size of the buffer is passed in bufSize. Use of sizes that are multiples of a memory page, a disk block, and so on, can have a significant positive impact on performance. This is, however, implementation-dependent. An optimal buffer size is generally dependent on the host operating system, the amount of memory available, and how the machine is configured. To make good use of buffering doesn’t necessarily require quite this degree of sophistication. A good guess for a size is around 8,192 bytes, and attaching even a rather small buffer to an I/O stream is always a good idea. That way, the low-level system can read blocks of data from the disk or network and store the results in your buffer. Thus, even if you are reading the data a byte at a time out of the InputStream, you will be manipulating fast memory most of the time.

 

Buffering an input stream also provides the foundation required to support moving backward in the stream of the available buffer. Beyond the read( ) and skip( ) methods implemented in any InputStreamBufferedInputStream also supports the mark( ) andreset( ) methods. This support is reflected by BufferedInputStream.markSupported( ) returning true.

 

The following example contrives a situation where we can use mark( ) to remember where we are in an input stream and later usereset( ) to get back there. This example is parsing a stream for the HTML entity reference for the copyright symbol. Such a reference begins with an ampersand (&) and ends with a semicolon (;) without any intervening whitespace. The sample input has two ampersands to show the case where the reset( ) happens and where it does not.

 

 

    //Use buffered input.

 

    //This program uses try-with-resources. It requires JDK 7 or later.

 

import java.io.*;

 

class BufferedInputStreamDemo {

 

public static void main(String args[]) {

 

String s = "This is a &copy; copyright symbol " + "but this is &copy not.\n";

 

byte buf[] = s.getBytes();

 

ByteArrayInputStream in = new ByteArrayInputStream(buf); int c;

 

boolean marked = false;

 

// Use try-with-resources to manage the file.

 

try ( BufferedInputStream f = new BufferedInputStream(in) )

{

 

while ((c = f.read()) != -1) { switch(c) {

 

case '&':

 

if (!marked) { f.mark(32); marked = true;

 

} else {

 

marked = false;

 

}

 

break; case ';':

 

if (marked) { marked = false;

 

System.out.print("(c)");

 

} else System.out.print((char) c);

 

break; case ' ':

 

if (marked) { marked = false; f.reset();

 

System.out.print("&");

 

} else System.out.print((char) c);

 

break;

 

default:

 

if (!marked) System.out.print((char) c);

 

break;

 

}

 

}

 

} catch(IOException e) { System.out.println("I/O Error: " + e);

}

 

}

 

}

 

Notice that this example uses mark(32), which preserves the mark for the next 32 bytes read (which is enough for all entity references). Here is the output produced by this program:

 

 

This is a (c) copyright symbol but this is &copy not.

 

BufferedOutputStream

 

BufferedOutputStream is similar to any OutputStream with the exception that the flush( ) method is used to ensure that data buffers are written to the stream being buffered. Since the point of a BufferedOutputStream is to improve performance by reducing the number of times the system actually writes data, you may need to call flush( ) to cause any data that is in the buffer to be immediately written.

Unlike buffered input, buffering output does not provide additional functionality. Buffers for output in Java are there to increase performance. Here are the two available constructors:

 

BufferedOutputStream(OutputStream outputStream) BufferedOutputStream(OutputStream outputStream, int bufSize)

 

The first form creates a buffered stream using the default buffer size. In the second form, the size of the buffer is passed in bufSize.

 

PushbackInputStream

 

One of the novel uses of buffering is the implementation of pushback. Pushback is used on an input stream to allow a byte to be read and then returned (that is, "pushed back") to the stream. The PushbackInputStream class implements this idea. It provides a mechanism to "peek" at what is coming from an input stream without disrupting it.

 

PushbackInputStream has the following constructors:

 

PushbackInputStream(InputStream inputStream)

PushbackInputStream(InputStream inputStream, int numBytes)

 

The first form creates a stream object that allows one byte to be returned to the input stream. The second form creates a stream that has a pushback buffer that is numBytes long. This allows multiple bytes to be returned to the input stream.

 

Beyond the familiar methods of InputStreamPushbackInputStream provides unread( ), shown here:

 

void unread(int b)

 

void unread(byte buffer [ ])

 

void unread(byte buffer, int offset, int numBytes)

 

The first form pushes back the low-order byte of b. This will be the next byte returned by a subsequent call to read( ). The second form pushes back the bytes in buffer. The third form pushes back numBytes bytes beginning at offset from buffer. An IOExceptionwill be thrown if there is an attempt to push back a byte when the pushback buffer is full.

Here is an example that shows how a programming language parser might use a PushbackInputStream and unread( ) to deal with the difference between the = = operator for comparison and the = operator for assignment:

 

    //Demonstrate unread().

 

    //This program uses try-with-resources. It requires JDK 7 or later.

 

import java.io.*;

 

class PushbackInputStreamDemo {

 

public static void main(String args[]) {

String s = "if (a == 4) a = 0;\n"; byte buf[] = s.getBytes();

 

ByteArrayInputStream in = new ByteArrayInputStream(buf); int c;

try ( PushbackInputStream f = new PushbackInputStream(in) )

 

{

 

while ((c = f.read()) != -1) { switch(c) {

 

case '=':

 

if ((c = f.read()) == '=') System.out.print(".eq.");

 

else { System.out.print("<-"); f.unread(c);

 

}

 

break;

 

default: System.out.print((char) c); break;

 

}

 

}

 

} catch(IOException e) { System.out.println("I/O Error: " + e);

}

 

}

 

}

 

Here is the output for this example. Notice that == was replaced by ".eq." and = was replaced by "<–".

 

if (a .eq. 4) a <- 0;

 

CAUTION  PushbackInputStream has the side effect of invalidating the mark( ) or reset( ) methods of the InputStream used to create it. Use markSupported( ) to check any stream on which you are going to use mark( )/reset( ).

 

SequenceInputStream

 

The SequenceInputStream class allows you to concatenate multiple InputStreams. The construction of a SequenceInputStream is different from any other InputStream. A

SequenceInputStream constructor uses either a pair of InputStreams or an Enumeration of InputStreams as its argument:

 SequenceInputStream(InputStream first, InputStream second)

SequenceInputStream(Enumeration <? extends InputStream> streamEnum)

Operationally, the class fulfills read requests from the first InputStream until it runs out and then switches over to the second one. In the case of an Enumeration, it will continue through all of the InputStreams until the end of the last one is reached. When the end of each file is reached, its associated stream is closed. Closing the stream created by SequenceInputStream causes all unclosed streams to be closed.

Here is a simple example that uses a SequenceInputStream to output the contents of two files. For demonstration purposes, this program uses the traditional technique used to close a file. As an exercise, you might want to try changing it to use the try-with-resources statement.

 

    //Demonstrate sequenced input.

 

    //This program uses the traditional approach to closing a file.

 

import java.io.*;

import java.util.*;

 

class InputStreamEnumerator implements Enumeration<FileInputStream> {

private Enumeration<String> files;

 

public InputStreamEnumerator(Vector<String> files) { this.files = files.elements();

 

}

 

public boolean hasMoreElements() { return files.hasMoreElements();

 

}

 

public FileInputStream nextElement() { try {

 

return new FileInputStream(files.nextElement().toString());

 

} catch (IOException e) { return null;

 

}

 

}

 

}

 

class SequenceInputStreamDemo {

 

public static void main(String args[]) { int c;

 

Vector<String> files = new Vector<String>();

 

files.addElement("file1.txt");

 

files.addElement("file2.txt");

 

files.addElement("file3.txt");

 

InputStreamEnumerator ise = new InputStreamEnumerator(files); InputStream input = new SequenceInputStream(ise);

 

try {

 

while ((c = input.read()) != -1) System.out.print((char) c);

 

} catch(NullPointerException e) { System.out.println("Error Opening File.");

 

} catch(IOException e) { System.out.println("I/O Error: " + e);

 

} finally { try {

input.close();

} catch(IOException e) {

 

System.out.println("Error Closing SequenceInputStream");

 

}

 

}

 

}

 

}

 

This example creates a Vector and then adds three filenames to it. It passes that vector of names to the InputStreamEnumeratorclass, which is designed to provide a wrapper on the vector where the elements returned are not the filenames but, rather, openFileInputStreams on those names. The SequenceInputStream opens each file in turn, and this example prints the contents of the files.

 

Notice in nextElement( ) that if a file cannot be opened, null is returned. This results in a NullPointerException, which is caught inmain( ).

 

PrintStream

 

The PrintStream class provides all of the output capabilities we have been using from the System file handle, System.out, since the beginning of the book. This makes PrintStream one of Java’s most often used classes. It implements the Appendable,AutoCloseable,

Closeable, and Flushable interfaces.

 

PrintStream defines several constructors. The ones shown next have been specified from the start:

 

PrintStream(OutputStream outputStream)

PrintStream(OutputStream outputStream, boolean autoFlushingOn)

PrintStream(OutputStream outputStream, boolean autoFlushingOn String charSet) throws UnsupportedEncodingException

 

Here, outputStream specifies an open OutputStream that will receive output. The autoFlushingOn parameter controls whether the output buffer is automatically flushed every time a newline (\n) character or a byte array is written or when println( ) is called. IfautoFlushingOn is true, flushing automatically takes place. If it is false, flushing is not automatic. The first constructor does not automatically flush. You can specify a character encoding by passing its name in charSet.

The next set of constructors gives you an easy way to construct a PrintStream that writes its output to a file:

 

PrintStream(File outputFile) throws FileNotFoundException PrintStream(File outputFile, String charSet)

throws FileNotFoundException, UnsupportedEncodingException PrintStream(String outputFileName) throws FileNotFoundException PrintStream(String outputFileName, String charSet) throws FileNotFoundException,

UnsupportedEncodingException

 

These allow a PrintStream to be created from a File object or by specifying the name of a file. In either case, the file is automatically created. Any preexisting file by the same name is destroyed.

Once created, the PrintStream object directs all output to the specified file. You can specify a character encoding by passing its name in charSet.

NOTE  If a security manager is present, some PrintStream constructors will throw a SecurityException if a security violation occurs.

 

PrintStream supports the print( ) and println( ) methods for all types, including Object. If an argument is not a primitive type, thePrintStream methods will call the object’s toString( ) method and then display the result.

Somewhat recently (with the release of JDK 5), the printf( ) method was added to PrintStream. It allows you to specify the precise format of the data to be written. The printf( ) method uses the Formatter class (described in Chapter 19) to format data. It then writes this data to the invoking stream. Although formatting can be done manually, by using Formatter directly, printf( )streamlines the process. It also parallels the C/C++ printf( ) function, which makes it easy to convert existing C/C++ code into Java. Frankly, printf( ) was a much welcome addition to the Java API because it greatly simplified the output of formatted data to the console.

 

The printf( ) method has the following general forms:

 

PrintStream printf(String fmtString, Object … args) PrintStream printf(Locale loc, String fmtString, Object … args)

 

The first version writes args to standard output in the format specified by fmtString, using the default locale. The second lets you specify a locale. Both return the invoking

 

PrintStream.

 

In general, printf( ) works in a manner similar to the format( ) method specified by Formatter. The fmtString consists of two types of items. The first type is composed of characters that are simply copied to the output buffer. The second type contains format specifiers that define the way the subsequent arguments, specified by args, are displayed. For complete information on formatting output, including a description of the format specifiers, see the Formatter class in Chapter 19.

Because System.out is a PrintStream, you can call printf( ) on System.out. Thus, printf( ) can be used in place of println( ) when writing to the console whenever formatted output is desired. For example, the following program uses printf( ) to output numeric values in various formats. Prior to JDK 5, such formatting required a bit of work. With the addition of printf( ), this is now an easy task.

 

// Demonstrate printf().

 

class PrintfDemo {

 

public static void main(String args[]) { System.out.println("Here are some numeric values " +

 

"in different formats.\n");

 

System.out.printf("Various integer formats: ");

 

System.out.printf("%d %(d %+d %05d\n", 3, -3, 3, 3);

 

System.out.println();

 

System.out.printf("Default floating-point format: %f\n", 1234567.123);

 

System.out.printf("Floating-point with commas: %,f\n", 1234567.123);

System.out.printf("Negative floating-point default: %,f\n", -1234567.123);

 

System.out.printf("Negative floating-point option: %,(f\n", -1234567.123);

 

System.out.println();

 

System.out.printf("Line up positive and negative values:\n"); System.out.printf("% ,.2f\n% ,.2f\n",

 

1234567.123, -1234567.123);

 

}

 

}

 

The output is shown here:

 

Here are some numeric values in different formats.

 

Various integer formats: 3 (3) +3 00003

 

Default floating-point format: 1234567.123000

 

Floating-point with commas: 1,234,567.123000

 

Negative floating-point default: -1,234,567.123000

 

Negative floating-point option: (1,234,567.123000)

 

Line up positive and negative values: 1,234,567.12

 

-1,234,567.12

 

PrintStream also defines the format( ) method. It has these general forms:

 

PrintStream format(String fmtString, Object … args)

PrintStream format(Locale loc, String fmtString, Object … args)

 

It works exactly like printf( ).

 

DataOutputStream and DataInputStream

 

DataOutputStream and DataInputStream enable you to write or read primitive data to or from a stream. They implement theDataOutput and DataInput interfaces, respectively. These interfaces define methods that convert primitive values to or from a sequence of bytes. These streams make it easy to store binary data, such as integers or floating-point values, in a file. Each is examined here.

DataOutputStream extends FilterOutputStream, which extends OutputStream. In addition to implementing DataOutput,DataOutputStream also implements AutoCloseable,

Closeable, and Flushable. DataOutputStream defines the following constructor: DataOutputStream(OutputStream outputStream)

Here, outputStream specifies the output stream to which data will be written. When a DataOutputStream is closed (by calling close( )), the underlying stream specified by outputStream is also closed automatically.

DataOutputStream supports all of the methods defined by its superclasses. However, it is the methods defined by the DataOutputinterface, which it implements, that make it interesting. DataOutput defines methods that convert values of a primitive type into a byte sequence and then writes it to the underlying stream. Here is a sampling of these methods:

 

final void writeDouble(double value) throws IOException final void writeBoolean(boolean value) throws IOException final void writeInt(int value) throws IOException

 

Here, value is the value written to the stream.

 

DataInputStream is the complement of DataOuputStream. It extends

 

FilterInputStream, which extends InputStream. In addition to implementing the DataInput interface, DataInputStream also implements AutoCloseable and

Closeable. Here is its only constructor:

 

DataInputStream(InputStream inputStream)

 

Here, inputStream specifies the input stream from which data will be read. When a DataInputStream is closed (by calling close( )), the underlying stream specified by inputStream is also closed automatically.

 

Like DataOutputStreamDataInputStream supports all of the methods of its superclasses, but it is the methods defined by theDataInput interface that make it unique. These methods read a sequence of bytes and convert them into values of a primitive type. Here is a sampling of these methods:

 

final double readDouble( ) throws IOException final boolean readBoolean( ) throws IOException final int readInt( ) throws IOException

 

The following program demonstrates the use of DataOutputStream and

 

DataInputStream:

 

    //Demonstrate DataInputStream and DataOutputStream.

 

    //This program uses try-with-resources. It requires JDK 7 or later.

 

import java.io.*;

 

class DataIODemo {

 

public static void main(String args[]) throws IOException {

 

// First, write the data.

try ( DataOutputStream dout =

 

new DataOutputStream(new FileOutputStream("Test.dat")) )

 

{

 

dout.writeDouble(98.6);

 

dout.writeInt(1000);

dout.writeBoolean(true);

} catch(FileNotFoundException e) {

System.out.println("Cannot Open Output File"); return;

 

} catch(IOException e) { System.out.println("I/O Error: " + e);

}

 

// Now, read the data back.

try ( DataInputStream din =

 

new DataInputStream(new FileInputStream("Test.dat")) )

 

{

 

double d = din.readDouble(); int i = din.readInt();

boolean b = din.readBoolean();

 

System.out.println("Here are the values: " + d + " " + i + " " + b);

 

} catch(FileNotFoundException e) { System.out.println("Cannot Open Input File"); return;

 

} catch(IOException e) { System.out.println("I/O Error: " + e);

}

 

}

 

}

 

The output is shown here:

 

Here are the values: 98.6 1000 true

 

RandomAccessFile

 

RandomAccessFile encapsulates a random-access file. It is not derived from InputStream or OutputStream. Instead, it implements the interfaces DataInput and DataOutput, which define the basic I/O methods. It also implements the AutoCloseableand Closeable interfaces. RandomAccessFile is special because it supports positioning requests—that is, you can position the file pointer within the file. It has these two constructors:

 

RandomAccessFile(File fileObj, String access)

throws FileNotFoundException

 

RandomAccessFile(String filename, String access)

throws FileNotFoundException

In the first form, fileObj specifies the file to open as a File object. In the second form, the name of the file is passed in filename. In both cases, access determines what type of file access is permitted. If

it is "r", then the file can be read, but not written. If it is "rw", then the file is opened in read-write mode. If it is "rws", the file is opened for read-write operations and every change to the file’s data or metadata will be immediately written to the physical device. If it is "rwd", the file is opened for read-write operations and every change to the file’s data will be immediately written to the physical device.

 

The method seek( ), shown here, is used to set the current position of the file pointer within the file:

 

void seek(long newPos) throws IOException

 

Here, newPos specifies the new position, in bytes, of the file pointer from the beginning of the file. After a call to seek( ), the next read or write operation will occur at the new file position.

 

RandomAccessFile implements the standard input and output methods, which you can use to read and write to random access files. It also includes some additional methods. One is setLength( ). It has this signature:

 

void setLength(long len) throws IOException

 

This method sets the length of the invoking file to that specified by len. This method can be used to lengthen or shorten a file. If the file is lengthened, the added portion is undefined.


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail
Java The Complete Reference : The Java Library : Input/Output: Exploring java.io : The Byte Streams - java.io |


Privacy Policy, Terms and Conditions, DMCA Policy and Compliant

Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.