Basic Input and Output - Platform - Java 8 Pocket Guide (2014)

Java 8 Pocket Guide (2014)

Part II. Platform

Chapter 12. Basic Input and Output

Java provides several classes for basic input and output, a few of which are discussed in this chapter. The basic classes can be used to read and write to files, sockets, and the console. They also provide for working with files and directories and for serializing data. Java I/O classes throw exceptions, including the IOException, which needs to be handled.

Java I/O classes also support for+matting data, compressing and decompressing streams, encrypting and decrypting, and communicating between threads using piped streams.

The new I/O (NIO) APIs that were introduced in Java 1.4 provide additional I/O capabilities, including buffering, file locking, regular expression matching, scalable networking, and buffer management.

NIO.2 was introduced with Java SE 7 and is covered in the next chapter. NIO.2 extends NIO and provides a new filesystem API.

Standard Streams in, out, and err

Java uses three standard streams: in, out, and err.

System.in is the standard input stream that is used to get data from the user to a program:

byte teamName[] = new byte[200];

int size = System.in.read(teamName);

System.out.write(teamName,0,size);

System.out is the standard output stream that is used to output data from a program to the user:

System.out.print("Team complete");

System.err is the standard error stream that is used to output error data from a program to the user:

System.err.println("Not enough players");

Note that each of these methods can throw an IOException.

TIP

The Console class, introduced in Java SE 6, provides an alternative to the standard streams for interacting with the command-line environment.

Class Hierarchy for Basic Input and Output

Figure 12-1 shows a class hierarchy for commonly used readers, writers, and input and output streams. Note that I/O classes can be chained together to get multiple effects.

The Reader and Writer classes are used for reading and writing character data (text). The InputStream and OutputStream classes are typically used for reading and writing binary data.

Figure 12-1. Common readers, writers, and input/output streams

File Reading and Writing

Java provides facilities to easily read and write to system files.

Reading Character Data from a File

To read character data from a file, use a BufferedReader. A FileReader can also be used, but it will not be as efficient if there is a large amount of data. The call to readLine() reads a line of text from the file. When reading is complete, call close() on the BufferedReader:

BufferedReader bReader = new BufferedReader

(new FileReader("Master.txt"));

String lineContents;

while ((lineContents = bReader.readLine())

!= null) {...}

bReader.close();

Consider using NIO 2.0’s Files.newBufferedReader(<path>,<charset>); to avoid the implicit assumption about the file encoding.

Reading Binary Data from a File

To read binary data, use a DataInputStream. The call to read() reads the data from the input stream. Note that if only an array of bytes will be read, you should just use InputStream:

DataInputStream inStream = new DataInputStream

(new FileInputStream("Team.bin"));

inStream.read();

If a large amount of data is going to be read, you should also use a BufferedInputStream to make reading the data more efficient:

DataInputStream inStream = new DataInputStream

(new BufferedInputStream(new FileInputStream(team)));

Binary data that has been read can be put back on the stream using methods in the PushbackInputStream class:

unread(int i); // pushback a single byte

unread(byte[] b); // pushback array of bytes

Writing Character Data to a File

To write character data to a file, use a PrintWriter. Call the close() method of class PrintWriter when writing to the output stream is complete:

String in = "A huge line of text";

PrintWriter pWriter = new PrintWriter

(new FileWriter("CoachList.txt"));

pWriter.println(in);

pWriter.close();

Text can also be written to a file using a FileWriter if there is a small amount of text to be written. Note that if the file passed into the FileWriter does not exist, it will automatically be created:

FileWriter fWriter = new

FileWriter("CoachList.txt");

fwriter.write("This is the coach list.");

fwriter.close();

Writing Binary Data to a File

To write binary data, use a DataOutputStream. The call to writeInt() writes an array of integers to the output stream:

File positions = new File("Positions.bin");

Int[] pos = {0, 1, 2, 3, 4};

DataOutputStream outStream = new DataOutputStream

(new FileOutputStream(positions));

for (int i = 0; i < pos.length; i++)

outStream.writeInt(pos[i]);

If a large amount of data is going to be written, then also use a BufferedOutputStream:

DataOutputStream outStream = new DataOutputStream

(new BufferedOutputStream(positions));

Socket Reading and Writing

Java provides facilities to easily read and write to system sockets.

Reading Character Data from a Socket

To read character data from a socket, connect to the socket and then use a BufferedReader to read the data:

Socket socket = new Socket("127.0.0.1", 64783);

InputStreamReader reader = new InputStreamReader

(socket.getInputStream());

BufferedReader bReader = new BufferedReader(reader);

String msg = bReader.readLine();

BufferedReader introduced the lines() method in Java SE 8, relative to the new Stream API. This method returns a Stream, the elements of which are lines lazily read from the contexted BufferedReader.

Reading Binary Data from a Socket

To read binary data, use a DataInputStream. The call to read() reads the data from the input stream. Note that the Socket class is located in java.net:

Socket socket = new Socket("127.0.0.1", 64783);

DataInputStream inStream = new DataInputStream

(socket.getInputStream());

inStream.read();

If a large amount of data is going to be read, then also use a BufferedInputStream to make reading the data more efficient:

DataInputStream inStream = new DataInputStream

(new BufferedInputStream(socket.getInputStream()));

Writing Character Data to a Socket

To write character data to a socket, make a connection to a socket and then create and use a PrintWriter to write the character data to the socket:

Socket socket = new Socket("127.0.0.1", 64783);

PrintWriter pWriter = new PrintWriter

(socket.getOutputStream());

pWriter.println("Dad, we won the game.");

Writing Binary Data to a Socket

To write binary data, use a DataOutputStream. The call to write() writes the data to an output stream:

byte positions[] = new byte[10];

Socket socket = new Socket("127.0.0.1", 64783);

DataOutputStream outStream = new DataOutputStream

(socket.getOutputStream());

outStream.write(positions, 0, 10);

If a large amount of data is going to be written, then also use a BufferedOutputStream:

DataOutputStream outStream = new DataOutputStream

(new BufferedOutputStream(socket.getOutputStream()));

Serialization

To save a version of an object (and all related data that would need to be restored) as an array of bytes, the class of this object must implement the interface Serializable. Note that data members declared transient will not be included in the serialized object. Use caution when using serialization and deserialization, as changes to a class—including moving the class in the class hierarchy, deleting a field, changing a field to nontransient or static, and using different JVMs—can all impact restoring an object.

The ObjectOutputStream and ObjectInputStream classes can be used to serialize and deserialize objects.

Serialize

To serialize an object, use an ObjectOutputStream:

ObjectOutputStream s = new

ObjectOutputStream(new FileOutputStream("p.ser"));

An example of serializing follows:

ObjectOutputStream oStream = new

ObjectOutputStream(new

FileOutputStream("PlayerDat.ser"));

oStream.writeObject(player);

oStream.close();

Deserialize

To deserialize an object (i.e., turn it from a flattened version of an object to an object), use an ObjectInputStream, then read in the file and cast the data into the appropriate object:

ObjectInputStream d = new

ObjectInputStream(new FileInputStream("p.ser"));

An example of deserializing follows:

ObjectInputStream iStream = new

ObjectInputStream(new

FileInputStream("PlayerDat.ser"));

Player p = (Player) iStream.readObject();

Zipping and Unzipping Files

Java provides classes for creating compressed ZIP and GZIP files. ZIP archives multiple files, whereas GZIP archives a single file.

Use ZipOutputStream to zip files and ZipInputSteam to unzip them:

ZipOutputStream zipOut = new ZipOutputStream(

new FileOutputStream("out.zip"));

String[] fNames = new String[] {"f1", "f2"};

for (int i = 0; i < fNames.length; i++) {

ZipEntry entry = new ZipEntry(fNames[i]);

File InputStream fin =

new FileInputStream(fNames[i]);

try {

zipOut.putNextEntry(entry);

for (int a = fin.read();

a != -1; a = fin.read()) {

zipOut.write(a);

}

fin.close();

zipOut.close();

} catch (IOException ioe) {...}

}

To unzip a file, create a ZipInputStream, call its getNextEntry() method, and read the file into an OutputStream.

Compressing and Uncompressing GZIP Files

To compress a GZIP file, create a new GZIPOutputStream, pass it the name of a file with the .gzip extension, and then transfer the data from the GZIPOutputStream to the FileInputStream.

To uncompress a GZIP file, create a GZipInputStream, create a new FileOutputStream, and read the data into it.