Java I/O, 2nd Edition: Table of Contents

[ Home Page | Examples | Why I Like Writing for O'Reilly | Interview with Peter Wayner | Order ]

Part I: Basic I/O

Traditional I/O in Java is based on a single metaphor, the stream. Programs read data out of input streams and write data onto output streams. To a large extent you don’t need to know whether the stream is a file, network socket, or something else, as long as you have a stream that points to it. Our exploration of I/O in Java naturally begins with this most fundamental abstraction.

Chapter 1: Introducing I/O

Chapter 1 describes the architecture and design of the package, including the reader/stream dichotomy. Some basic preliminaries about the int, byte, and char data types are discussed. The IOException thrown by many I/O methods is introduced. The console is introduced, along with some stern warnings about its proper use. Finally, I offer a cautionary message about how the security manager can interfere with most kinds of I/O, sometimes in unexpected ways.

Chapter 2: Output Streams

Chapter 2 explores the OutputStream class you need to write data onto any output stream. You’ll learn about the three overloaded versions of write() as well as flush() and close(). You’ll see several examples, including a simple subclass of OutputStream that acts like /dev/null and a text area component that gets its data from an output stream.

Chapter 3: Input Streams

The third chapter introduces the InputStream class. You’ll learn about the three overloaded variants of the read() method and when to use each. You’ll see how to skip over data and check how much data is available as well as how to place a bookmark in an input stream and reset back to that point. You’ll learn how and why to close input streams. This is all drawn together with a StreamCopier program that copies data read from an input stream onto an output stream. This program is used repeatedly over the next several chapters.

Part II: Data Sources

Part II talks about the two most common targets of I/O, the filesystem and the network. While both are accessed using input and output streams, some critical differences in setup and performance characteristics make them worth exploring separately.

Chapter 4: File Streams

The majority of I/O involves reading or writing files. Chapter 4 introduces the FileInputStream and FileOutputStream classes, concrete subclasses of InputStream and OutputStream that let you read and write files. Also in this chapter, I begin development of a File Viewer program, an example that will grow throughout the book. This initial version prints the raw bytes in a file in both decimal and hexadecimal format.

Chapter 5: Network Streams

From its first days, Java has always had the network in mind, more so than any other common programming language. Java was the first programming language to provide as much support for network I/O as it does for file I/O, perhaps even more. Chapter 5 introduces the URL, URLConnection, Socket, and ServerSocket classes, all fertile sources of streams. Examples in this chapter include several simple web and email clients.

Part III: Filter Streams

Some of the most interesting possibilities arise when you use streams not just for input and output but also for processing. Streaming processing simplifies code, vastly reduces memory usage, and dramatically increases perceived performance. A lot can happen when you don’t try to read everything into a memory structure at once. Filter streams are Java’s mechanism for processing data as you read or write, rather than waiting till later.

Chapter 6: Filter Streams

Chapter 6 introduces filter streams. Filter input streams read data from a preexisting input stream like a FileInputStream and work with or change the data before it is delivered to the client program. Filter output streams write data to a preexisting output stream such as a FileOutputStream and process the data before it is written onto the underlying stream. Multiple filters can be chained onto a single underlying stream to combine the functionality offered by several filters. Filter streams are used for encryption, compression, translation, buffering, and much more. At the end of this chapter, the File Viewer program is redesigned around filter streams to make it more extensible.

Chapter 7: Print Streams

Chapter 7 introduces PrintStream. The most familiar example of a PrintStream is System.out used for the very first Hello World example. However, starting in Java 5, the familiar PrintStream class has become a lot more powerful and interesting. Besides basic console output, it now provides extensive capabilities for formatting numbers and dates in a straightforward and easy fashion.

Chapter 8: Data Streams

Chapter 8 introduces data streams for writing strings, integers, floating-point numbers, and other data that’s commonly presented at a level higher than mere bytes. The DataInputStream and DataOutputStream classes read and write the primitive Java data types (boolean, int, double, etc.) and strings in a particular, well-defined, platform-independent format. Along the way, you’ll develop classes to read and write little-endian numbers, and you’ll extend the File Viewer program to handle big- and little-endian integers and floating-point numbers of varying widths.

Chapter 9: Streams in Memory

Chapter 9 shows you how streams can move data from one part of a running Java program to another. There are three main ways to do this. Sequence input streams chain several input streams together so that they appear as a single stream. Byte array streams allow output to be stored in byte arrays and input to be read from byte arrays. Finally, piped input and output streams turn output from one thread into input for another thread.

Chapter 10: Compressing Streams

Chapter 10 explores the package that reads and writes data in zip and gzip formats. Java uses these classes to read and write JAR archives and to display PNG images. However, the classes can also be used for general-purpose compression and decompression. In the final example, support for compressed files is added to the File Viewer program.

Chapter 11: JAR Archives

Many Java programs store content in JAR archives. Among other uses, this makes it easy to bundle many different files and resources into a single distributable. Chapter 11 explores the java.util.jar packages used to read these archives. In this chapter, you’ll learn when to replace filesystems with unitary JAR archives, how to put content into those archives, and how to get it back out again.

Chapter 12: Cryptogrpahic Streams

The core Java API contains two cryptography-related filter streams in the package, DigestInputStream and DigestOutputStream. There are two more in the javax.crypto package, CipherInputStream and CipherOutputStream, available in the Java Cryptography Extension (JCE for short). Chapter 12 shows you how to use these classes to encrypt and decrypt data using a variety of algorithms, including DES and Blowfish. You’ll also learn how to calculate message digests for streams that can be used for digital signatures. In the final example, support for encrypted files is added to the File Viewer program.

Chapter 13: Object Serialization

Most I/O is performed with bytes. Occasionally larger types like ints, floats, and doubles are converted to bytes and written as well. However, most actual programming is done with classes and objects. Object serialization lets you read and write almost arbitrary objects onto a stream. This chapter shows you how to read and write objects as well as how to customize the format used for serialization.

Part IV: New I/O

Java 1.4 introduced a completely new I/O model based on channels and buffers instead of streams. This model doesn’t replace traditional stream-based I/O for many uses. However, it is significantly faster in one important use case: servers that process many simultaneous clients.

Chapter 14: Buffers

Chapter 14 introduces the buffer classes that underlie all of the new I/O model. It demonstrates the use of the new I/O classes to read and write files and shows how memory-mapped I/O enables you to read and write truly huge files efficiently with limited memory.

Chapter 15: Channels

Chapter 15 moves the new I/O model onto the network with channels. You’ll learn how to combine channels through scattering and gathering, how to communicate over sockets with channels, and how to transmit UDP packets in the new I/O model.

Chapter 16: Nonblocking I/O

The real performance gain of new I/O is in highly multiprocessing servers. This chapter demonstrates the use of nonblocking I/O to dramatically increase the number of simultaneous clients one program can serve. You’ll learn about selectors, selection keys, attachments, and pipe channels.

Part V: The File System

When you think of I/O, the first thing that comes to mind is files. Part V discusses operations on files themselves as distinct from the contents of those files. This includes moving, deleting, renaming, and choosing them.

Chapter 17: Working with Files

Files can be moved, deleted, renamed, and copied. Files usually have metadata such as the time the file was created, the icon for the file, and the permissions that determine which users can read or write the file. Chapter 17 shows you how to do all this and elaborates the precautions you need to take to make your file code portable across all major platforms that support Java.

Chapter 18: File Dialogs and Choosers

Filenames are problematic, even if you don’t have to worry about cross-platform idiosyncrasies. Users forget names, mistype them, can’t remember the exact path to files they need, and more. The proper way to ask a user to choose a file is to show them a list of the files and ask them to pick one. Most graphical user interfaces provide standard graphical widgets for selecting a file. In Java, the platform’s native file selector widget is exposed through the java.awt.FileDialog class. Like many native peer-based classes, however, FileDialog doesn’t behave the same or provide the same services on all platforms. Therefore, Swing provides a pure Java implementation of a file dialog, the javax.swing.JFileChooser class. Chapter 18 shows you how to use both these classes. In the final example, you’ll add a Swing-based GUI to the File Viewer program.

Part VI: Text

I/O is based on bytes, but much of that I/O has a larger structure as text. Part VI explores how text is represented in Java and how it can be manipulated through special text streams called readers and writers.

Chapter 19: Character Sets and Unicode

All Java chars and strings are given in Unicode. However, since there’s also a lot of non-Unicode legacy text in the world, in a dizzying array of encodings, Java also provides the classes you need to read and write text in these encodings as well. Chapter 19 introduces you to the multitude of character sets used around the world and the java.nio.charsets package used to make sense out of this panoply.

Chapter 20: Readers and Writers

A language that supports international text must separate the reading and writing of raw bytes from the reading and writing of characters since in an international system they are no longer the same thing. Classes that read and write characters must be able to parse a variety of character encodings, not just ASCII, and translate them to and from the language’s native String and char types. The Reader and Writer classes perform this task. Chapter 20 shows you how to use these classes to add support for multilingual text to the File Viewer program.

Chapter 21: Formatted I/O with java.text

Computers process numbers, not words. When outputting binary numbers as decimal strings for humans to read, the java.text.NumberFormat class controls the width, precision, and alignment of the resulting numeric strings. NumberFormat can also localize numbers with different character sets, thousands separators, decimal points, and digit characters. Chapter 21 shows you how to use this class and its subclasses for traditional tasks like lining up the decimal points in a table of prices, and nontraditional tasks like formatting numbers in Egyptian Arabic.

Part VII: Devices

Not everything’s a filesystem or a network. I/O also includes talking to other kinds of devices: laboratory sensors, PDAs, and human input devices like mice and keyboards. While common devices like mice and keyboards are addressed through higher level APIs, less common devices like laboratory equipment are not. This section shows you how to communicate with different kinds of peripherals and small devices that don’t have traditional filesystems or network connections.

Chapter 22: The Java Communications API

Chapter 22 introduces the Java Communications API, a standard extension that allows Java applications to send and receive data to and from the serial and parallel ports of the host computer. The Java Communications API allows your programs to communicate with essentially any device connected to a serial or parallel port, like a printer, a scanner, or a modem.

Chapter 23: USB

Serial and parallel ports are still found on a lot of legacy equipment, but most new devices have moved on. USB is the next generation serial connector, and Java supports it. Chapter 23 shows you how to talk to a variety of USB devices using the Java USB API. In particular, it demonstrates collecting data from a USB-enabled laboratory temperature probe.

Chapter 24: The J2ME Generic Connection Framework

Some small devices are computers in their own rights: Palm Pilots, cell phones, programmable calculators, and more. However, these devices don’t always have the CPU speed, memory, or battery life necessary to run a full-scale Java VM. Many of them run one of a variety of slimmed-down virtual machines that collectively go under the name J2ME. The standard and packages are too heavyweight to fit in many such small devices. This chapter introduces the smaller, simpler Generic Connection Framework (GCF) and package that replace the standard I/O library on such small devices.

Chapter 25: Bluetooth

Increasingly, small devices don’t even need cables to connect to a host system. Instead, they transmit data over the air using Bluetooth. Chapter 25 explores the Java API for Bluetooth and shows you how Java programs can talk to Bluetooth devices wirelessly using the Generic Connection Framework. An example shows how to read location data from a Bluetooth GPS receiver.

[ Cafe au Lait | Home Page | Examples | Why I Like Writing for O'Reilly | Interview | Order ]

Copyright 2006 Elliotte Rusty Harold
Last Modified May 16, 2006