Design Philosophy

The design philosophy for Java I/O is based on these principles:

  • Programs that do I/O should be portable, even though I/O has some non-portable aspects. Platform differences in file names and line terminators must be handled in a way that ensures the code runs everywhere.

  • I/O is based on streams. A stream has a physical “device” at one end, like a file or a location in memory. That physical device is managed by some class, and you wrap (layer) additional logical classes on top of that for specific kinds of I/O.

  • There are lots of small classes that do one thing, instead of a few big classes that do many things. There is one class that interprets data in binary format, and another class that reads data from a file. If you want to read binary data from a file, you use both of these classes. The constructors make it convenient to use the classes together.

We'll see examples of these principles throughout the chapter. This is a long chapter, but a worthy one. To help you get the most out of it, Figure 17-1 represents the topics that will be covered, and how they are grouped together. As you can see, many of the I/O topics are freestanding and only relate to each other in a general way. If you feel lost at some point in this chapter, refer back to Figure 17-1.

Figure 17-1. Topics in I/O

image

The first three boxes in Figure 17-1 are covered in this chapter, and the next two in Chapter 18, “Advanced Input Output.” We'll start by looking at the File and FileDescriptor classes that provide a convenient way to represent a filename in Java. Then we'll cover Java support for interactive input (new in JDK 1.5). We'll round out the chapter by reviewing the most widely used input/output classes.

Portability of I/O

The basic portability approach of the Java run-time library is to have the same method do slightly different things appropriate to each platform. The standard end-of-line sequence on Windows is “carriage return, linefeed,” while on Unix it is just “linefeed.” Any library method that writes an end-of-line sequence, such as System.out.println(), will output a “carriage return, linefeed” pair on Windows, and a linefeed when running on Unix. In contrast, any string data where you wrote a literal ' ' (line feed) or ' ' (carriage return) in a string will be output on every platform exactly as you wrote it.

Table 17-2 shows some I/O-related platform differences. The column labelled Java feature shows the approach Java takes to minimize these differences.

Table 17-2. Platform differences in I/O

MS Windows

Unix

Java feature

End-of-line characters

System.getProperty ( "line.separator" )

Filename separator

''

'/'

java.io.File.separator

Pathnames

volume:cd or \hostsharecd

/a/b/c/d

Pass pathname to program as an argument

Data byte order

Little-endian

Varies with hardware

Big-endian, see Big-endian storage on page 454

If you have some legacy code that requires the actual end-of-line sequence, you can obtain it with the following method call:

String actualEOL = java.lang.System.getProperty("line.separator");

That statement will put the EOL sequence used by this platform into the variable. The println() methods of PrintWriter and PrintStream also output the EOL sequence of the specific platform. The I/O API often allows a file to be identified in two parts: the directory it is in, and the filename. That allows you to split off the platform-sensitive directory pathname from the comparatively portable filename string.

There is a field in the class java.io.File that contains the filename separator, which is a backslash on Windows and a forward slash on Unix. Instead of writing a pathname as "/a/b/c.txt," you can write it using the separator character, ensuring that it will be correct on all platforms. If you insist on reducing portability by using literal strings for pathnames, remember that backslash is also the string escape character. Therefore, you have to write it twice (to escape itself) when writing literal file names for the PC. Here is an example:

String myFile = "\a\b\c.txt";

You can actually use “/” to separate components in a Windows pathname in a program. The Windows file system calls all use it internally. The Windows interactive shell, COMMAND.COM, is the only part of the system that can't handle it. This is an interesting historical artifact, dating from the origins of MS-DOS as an unauthorized port (known as QDOS) of CP/M with a few trivial changes. That port was renamed to MS-DOS, licensed to IBM by Microsoft, only then bought by Microsoft so it could deliver on its licensing commitment, and the rest is history. Most programmers form a filename by declaring a variable with a briefer name to represent the separator character, like this:

final String s = java.io.File.separator;
String myFile = s + "a" + s + "b" + s + "c.txt";

This helps, but does not provide 100% data file portability because it doesn't mention the Windows drive. One approach to minimizing the differences is to tell the program its data filenames at run-time, either as command-line arguments or as system properties.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.251.128