Errata

Java I/O

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Printed
Page 8
The following paragraph and code fragment have been deleted

Even simple arithmetic with small, byte-valued constants as follows
produces "Explicit cast needed to convert int to byte" errors:

byte b = 1 + 2;

This is not true in Java 1.1 and later.

Anonymous    Feb 01, 2001
Printed
Page 9
In the middle of the page, the arithmetic algorithm given for

finding the last byte of the number was incorrect for negative numbers.
That section now reads like this:

This is the effect of taking the remainder modulo
256 of the int b and adding 256 if the value is negative; that is,

b = b % 256 >= 0 ? b % 256 : 256 + b % 256;

More simply, using bitwise operators,

b = b & 0x000000FF;

Anonymous    Jun 01, 1999
Printed
Page 10
In the fifth paragraph changed "the absolute value of the number"

to "the absolute value of a negative number"

Anonymous    Jun 01, 1999
Printed
Page 10
In the line of code near the top of the page, the

greater than sign is now greater than or equals; that is,

int unsignedByte = signedByte >= 0 ? signedByte : 256 + signedByte;

Anonymous    Jan 01, 2000
Printed
Page 13

In the last paragraph, line 5 used to read:

seven-bit character set called EBCDIC

It now reads:

eight-bit character set called EBCDIC

Anonymous    Jun 01, 1999
Printed
Page 15
In Java 1.1 and later, compilers can figure out if an operation

performed on char literals (though not char variables) will overflow the
bounds of a char. Thus the paragraph beginning, "A char used
in arithmetic..." and the following code fragment and paragraph have been
changed to:

A char used in arithmetic is promoted to int. This presents the same
problems as it does for bytes. Admittedly, performing mathematical
operations on chars is a much less common thing to want to do than
performing them on bytes.

Anonymous    Feb 01, 2001
Printed
Page 20
In the last paragraph "Microsoft Internet Explorer does not have

a visible console" has been changed to "Some versions of Microsoft
Internet Explorer do not have a visible console".

Anonymous    Jan 01, 2000
Printed
Page 21
In the second paragraph of the System.out section, "Hello World"

has been changed to "Hello World!"

Anonymous    Jan 01, 2000
Printed
Page 23
In the first paragraph on the page,

"For example, if the user types "Hello World", the
following bytes will be read from System.in in this order:"

has been changed to:

"For example, if the user types "Hello World!" and hits
the return or enter key, the following bytes will be
read from System.in in this order:"

Anonymous    Jan 01, 2000
Printed
Page 27
In the last paragraph "a linefeed and a tab, respectively"

now reads "a tab and a linefeed, respectively".

Anonymous    Jun 01, 1999
Printed
Page 27

Example 2-1 now reads:

import java.io.*;

public class AsciiChart {

public static void main(String[] args) {

for (int i = 32; i < 127; i++) {
System.out.write(i);
// break line after every eight characters
if (i % 8 == 7) System.out.write('
');
else System.out.write(' ');
}
System.out.write('
');

}

}

Anonymous    Jun 01, 1999
Printed
Page 29
At the start of the last paragraph, "Many operating systems

buffer writes" now reads "Many output streams buffer writes".

Anonymous    Jan 01, 2000
Printed
Page 30
The first paragraph has been changed to the following

"This is not the same as any buffering performed by the
operating system or the hardware. These buffers will not
be emptied by a call to flush(). (Then sync() method in the
FileDescriptor class, discussed in Chapter 12, can sometimes
be used to empty these buffers.) For example, assuming out
is an OutputStream of some sort,"

Anonymous    Jan 01, 2000
Printed
Page 38
The while loop in the code fragment at the bottom of

the page is missing a closing }. It now reads:

try {
byte[] b = new byte[100];
int offset = 0;
while (offset < b.length) {
int a = System.in.available();
int bytesRead = System.in.read(b, offset, a);
if (bytesRead == -1) break; // end of stream
offset += bytesRead;
}
}
catch (IOException e) {
System.err.println("Couldn't read from System.in!");
}

Anonymous    Jan 01, 2000
Printed
Page 40
In the first code example in.strip has been changed to in.skip

Anonymous    Jun 01, 1999
Printed
Page 43
example 3-3

the try block should say -
try {
copy(System.in, System.out);
}

(the line "copy(System.in, System.out);" was left out of the [1/02] printing)

Anonymous   
Printed
Page 43-44
The last paragraph on p. 44 has been deleted. The comment

in the copy() method on p. 43 has also been deleted.

Anonymous    Jan 01, 2000
Printed
Page 49

In Example 4-1, the line which used to read:

System.err.println("Usage: java FileCopier file1 file2 ...");

Now reads:

System.err.println("Usage: java FileTyper file1 file2 ...");

Anonymous    Jun 01, 1999
Printed
Page 54
In Example 4-3, changed

if (args.length < 1) {
System.err.println("Usage: java FileDumper [-ahd] file1 file2...");
}

to

if (args.length < 1) {
System.err.println("Usage: java FileDumper [-ahd] file1 file2...");
return;
}

Anonymous    Jun 01, 1999
Printed
Page 60
First Paragraph under "Scatter/Gather"

Fourth sentence reads "The buffers do not need to have the same capcity..." should
this read "The buffers do not need to have the same capacity..."?

Anonymous   
Printed
Page 60
The author was a little cavalier with my description of the

code base which is really a directory rather than a host. It used to
read:

"Applets running under the control of a security manager--that
is untrusted applets that run inside a web browser--are normally
only allowed to connect back to their code base. The code base is
the host from which they were downloaded, as returned by the
getCodeBase() method of the Applet class."

Now reads:

"Applets running under the control of a security manager--that
is untrusted applets that run inside a web browser--are normally
only allowed to connect back to the host they were downloaded
from. This host can be determined from the URL returned by the
getCodeBase() method of the Applet class."

Anonymous    Jan 01, 2000
Printed
Page 70
Changed

Socket s = s.accept();

to

Socket s = ss.accept();

in both examples.

Anonymous    Jun 01, 1999
Printed
Page 83
In Example 6-3 changed

else if (b == 10 || b == 13 || b == 9) return b;

to

else if (b == 10 || b == 13 || b == 9 || b == -1) return b;

Also changed

if (data[i] == 10 || data[i] == 13 || data[i] == 9) ;

to

if (data[i] == 10 || data[i] == 13 || data[i] == 9 || data[i] == -1) ;

Anonymous    Jun 01, 1999
Printed
Page 86
In the second paragraph on the page "the copy method" is now "the

copy() method" and copy() is in a monospaced font.

Anonymous    Jan 01, 2000
Printed
Page 87
In the second paragraph, "the index of the next byte that will be

returned by read()" now reads "the index of the next place in the array
where a byte will be stored"

Anonymous    Jan 01, 2000
Printed
Page 100

In Example 6-12, the line which used to read:

System.err.println("Usage: java FileDumper [-ahd] file1 file2...");

Now reads:

System.err.println("Usage: java FileDumper2 [-ahd] file1 file2...");

Anonymous    Jun 01, 1999
Printed
Page 100
In Example 6-12

if (args.length < 1) {
System.err.println("Usage: java FileDumper [-ahd] file1 file2...");
}

now reads:

if (args.length < 1) {
System.err.println("Usage: java FileDumper2 [-ahd] file1 file2...");
return;
}

(This is a correction to a previous correction.)

Anonymous    Jan 01, 2000
Printed
Page 111
In the last paragraph, the sentence

Doubles take up eight bytes with a one-bit sign, 11-bit mantissa,
and 53-bit exponent.

Has been changed to:

Doubles take up eight bytes with a one-bit sign, 53-bit mantissa,
and 11-bit exponent"

Anonymous    Jun 01, 1999
Printed
Page 115
The first code fragment has been changed to

int offset = 0;
while (true){
int bytesRead = in.read(data, offset, data.length - offset);
offset += bytesRead;
if (bytesRead == -1 || offset >= data.length) break;
}

Anonymous    Jan 01, 2000
Printed
Page 118

In the sidebar "Most of the time this is a bug" now reads:

"Most of the time this is a benign bug"

Anonymous    Jun 01, 1999
Printed
Page 126
There are bugs in the UTF methods in Examples 7-8 and 7-9.

To fix them in Example 7-8 changed the writeUTF() method and
preceding comments as follows:

/**
* Writes a string of no more than 65,535 characters
* to the underlying output stream using UTF-8
* encoding. This method first writes a two byte short
* in <b>big</b> endian order as required by the
* UTF-8 specification. This gives the number of bytes in the
* UTF-8 encoded version of the string, not the number of characters
* in the string. Next each character of the string is written
* using the UTF-8 encoding for the character.
*
* @param s the string to be written.
* @exception UTFDataFormatException if the string is longer than
* 65,535 characters.
* @exception IOException if the underlying stream throws an IOException.
*/
public void writeUTF(String s) throws IOException {

int numchars = s.length();
int numbytes = 0;

for (int i = 0 ; i < numchars ; i++) {
int c = s.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) numbytes++;
else if (c > 0x07FF) numbytes += 3;
else numbytes += 2;
}

if (numbytes > 65535) throw new UTFDataFormatException();

out.write((numbytes >>> 8) & 0xFF);
out.write(numbytes & 0xFF);
for (int i = 0 ; i < numchars ; i++) {
int c = s.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out.write(c);
}
else if (c > 0x07FF) {
out.write(0xE0 | ((c >> 12) & 0x0F));
out.write(0x80 | ((c >> 6) & 0x3F));
out.write(0x80 | (c & 0x3F));
written += 2;
}
else {
out.write(0xC0 | ((c >> 6) & 0x1F));
out.write(0x80 | (c & 0x3F));
written += 1;
}
}

written += numchars + 2;

}

Anonymous    Jun 01, 1999
Printed
Page 128

In the third paragraph, Double.longBitsToDouble() now reads:

Double.doubleToLongBits()

Anonymous    Jun 01, 1999
Printed
Page 130

The readShort() method near the bottom of the page now reads:

public short readShort() throws IOException {

int byte1 = in.read();
int byte2 = in.read();
// only need to test last byte read
// if byte1 is -1 so is byte2
if (byte2 == -1) throw new EOFException();
return (short) ((byte2 << 8) + byte1);

}

Anonymous    Jun 01, 1999
Printed
Page 131
Similarly, changed the readUnsignedShort method near the

top of the page:

public int readUnsignedShort() throws IOException {

int byte1 = in.read();
int byte2 = in.read();
if (byte2 == -1) throw new EOFException();
return (byte2 << 8) + byte1;

}

Anonymous    Jun 01, 1999
Printed
Page 133
The readUTF() method has been changed. Here's the revised

version:

/**
* Reads a string of no more than 65,535 characters
* from the underlying input stream using UTF-8
* encoding. This method first reads a two byte short
* in <b>big</b> endian order as required by the
* UTF-8 specification. This gives the number of bytes in
* the UTF-8 encoded version of the string.
* Next this many bytes are read and decoded as UTF-8
* encoded characters.
*
* @return the decoded string
* @exception UTFDataFormatException if the string cannot be decoded
* @exception IOException if the underlying stream throws an IOException.
*/
public String readUTF() throws IOException {

int byte1 = in.read();
int byte2 = in.read();
if (byte2 == -1) throw new EOFException();
int numbytes = (byte1 << 8) + byte2;

char result[] = new char[numbytes];
int numread = 0;
int numchars = 0;

while (numread < numbytes) {

int c1 = readUnsignedByte();

int c2, c3;

// look at the first four bits of c1 to determine how many
// bytes in this char
int test = c1 >> 4;
if (test < 8) { // one byte
numread++;
result[numchars++] = (char) c1;
}
else if (test == 12 || test == 13) { // two bytes
numread += 2;
if (numread > numbytes) throw new UTFDataFormatException();
c2 = readUnsignedByte();
if ((c2 & 0xC0) != 0x80) throw new UTFDataFormatException();
result[numchars++] = (char) (((c1 & 0x1F) << 6) | (c2 & 0x3F));
}
else if (test == 14) { // three bytes
numread += 3;
if (numread > numbytes) throw new UTFDataFormatException();
c2 = readUnsignedByte();
c3 = readUnsignedByte();
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException();
}
result[numchars++] = (char)
(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
else { // malformed
throw new UTFDataFormatException();
}

} // end while

return new String(result, 0, numchars);

}

Anonymous    Jun 01, 1999
Printed
Page 136
At the top of the page, the lines of code have been replaced with

this paragraph:

"However, this would only prevent another thread from
reading from the underlying input stream if the second
thread also synchronized on the underlying input stream.
In general you can't count on this, so it's not really a
solution. In fact, Java really doesn't provide a good
means to guarantee thread safety when you have to modify
objects you don't control passed as arguments to your methods."

Anonymous    Jan 01, 2000
Printed
Page 137
In the first paragraph, "<CODE>DumpFilter</CODE> from Chapter 4"

now reads "<CODE>DumpFilter</CODE> from Chapter 6"

Anonymous    Jun 01, 1999
Printed
Page 137

In Example 7-10, the line which used to read:

"Usage: java FileDumper2 [-ahdsilfx] [-little] file1 file2...");

Now reads:

"Usage: java FileDumper3 [-ahdsilfx] [-little] file1 file2...");

Anonymous    Jun 01, 1999
Printed
Page 141
In Figure 7-1 LEShortFilter is now connected to LEFilter, not to

DataFilter

Anonymous    Jun 01, 1999
Printed
Page 146

Near the bottom of the page "Th ByteArrayInputStream class reads:

data" now reads "The ByteArrayInputStream class reads data"

Anonymous    Jun 01, 1999
Printed
Page 148
The code fragment at the top of the page used to have an i <= 1024

instead of r < 1024. The entire fragment now reads:

"ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
DataOutputStream dos = new DataOutputStream(bos);
for (int r = 1; r <= 1024; r++) {
dos.writeDouble(r * 2.0 * Math.PI);
}"

Anonymous    Jan 01, 2000
Printed
Page 151

The fourth paragraph used to read:

There are two possible blocking situations here. The first occurs if the
writing thread tries to write data while the reading threads input buffer
is full. When this occurs, the input stream enters an infinite a loop in
which it repeatedly waits for one second until some thread reads some data
out of the buffer and frees up space. The second possible block is when the
reading thread tries to read and no data is present in the buffer. In this
case, the input stream enters an infinite a loop in which it repeatedly
waits for one second until some thread writes some data into the buffer. If
this is likely to be a problem for your application, you should subclass
PipedInputStream and provide a larger value for PIPE_SIZE.

It has been revised like this:

There are two possible blocking situations here. The first occurs if the
writing thread tries to write data while the reading threads input buffer
is full. When this occurs, the input stream enters an infinite a loop in
which it repeatedly waits for one second until some thread reads some data
out of the buffer and frees up space. If this is likely to be a problem for
your application, you should subclass PipedInputStream and make buffer
larger. The second possible block is when the reading thread tries to read
and no data is present in the buffer. In this case, the input stream enters
an infinite a loop in which it repeatedly waits for one second until some
thread writes some data into the buffer.

Anonymous    Jun 01, 1999
Printed
Page 151

In the third line of code at the top of the page, it used to read:

pin.connect(pos)

It now reads:

pin.connect(pout)

Anonymous    Jan 01, 2000
Printed
Page 156
In Figure 9-1, OutputString is now OutputStream.

Anonymous    Jan 01, 2000
Printed
Page 157
Step 7 now reads "go back to step 5", not "go back to step 4"

Anonymous    Jun 01, 1999
Printed
Page 165

Right before the Inflating Data section, the line used to read:

System.out.println((1.0 - def.getTotalOut()/def.getTotalIn())
*100.0 + '% saved')

Now reads:

System.out.println((1.0 - def.getTotalOut()/def.getTotalIn())
*100.0 + "% saved")

That is, the single quotes around % saved are now double quotes.

Anonymous    Jan 01, 2000
Printed
Page 165
In Step 6 "go back to step 4" now reads "go back to step 2"

Anonymous    Jan 01, 2000
Printed
Page 167
At the end of the fourth paragraph "insert more uncompressed input

data" now reads "insert more compressed input data". In the fifth paragraph
"feed in more uncompressed input data" now reads "feed in more compressed
input data".

Anonymous    Jan 01, 2000
Printed
Page 183
Example 9-9, FancyZipLister, did not calculate the savings

correctly due to integer (as opposed to floating
point) division. The corrected lines look like this:

else if (method == ZipEntry.DEFLATED) {
System.out.println(name + " was deflated at " + lastModified);
System.out.println("from " + uncompressedSize + " bytes to "
+ compressedSize + " bytes, a savings of "
+ (100.0 - 100.0*compressedSize/uncompressedSize) + "%");

}
else {
System.out.println(name
+ " was compressed using an unrecognized method at "
+ lastModified);
System.out.println("from " + uncompressedSize + " bytes to "
+ compressedSize + " bytes, a savings of "
+ (100.0 - 100.0*compressedSize/uncompressedSize) + "%");
}

Anonymous    Jun 01, 1999
Printed
Page 186
At the start of the first paragraph not in the list "Steps 4 and 6"

now reads "Steps 4 and 8".

Anonymous    Jun 01, 1999
Printed
Page 188
In the code fragment in the middle of the page,


InetAddress.getHostByName("sunsite.unc.edu")

Now reads:

InetAddress.getByName("sunsite.unc.edu").

The whole code fragment now reads:

try {
ServerSocket httpd = new ServerSocket(5776, 100,
InetAddress.getByName("sunsite.unc.edu"));
}
catch (IOException e) {
System.err.println(e);
}

Anonymous    Jan 01, 2000
Printed
Page 194
1st paragraph, 6th line

"the byte 3 (binary 00000011)"

has been changed to:

"the byte 7 (binary 00000111)".

Although 3 is an odd number,
it actually does have an even number of one bits.

Anonymous    Feb 01, 2001
Printed
Page 201
In the last paragraph, "as well the programs" now reads "as well as

the programs".

Anonymous    Jun 01, 1999
Printed
Page 206
Example 9-14, JarLister had the same bug as problem as FancyZipLister.

The fix is the same too. Changed the else and else if blocks as follows:

else if (method == ZipEntry.DEFLATED) {
System.out.println(name + " was deflated at " + lastModified);
System.out.println("from " + uncompressedSize + " bytes to "
+ compressedSize + " bytes, a savings of "
+ (100.0 - 100.0*compressedSize/uncompressedSize) + "%");
}
else {
System.out.println(name
+ " was compressed using an unrecognized method at "
+ lastModified);
System.out.println("from " + uncompressedSize + " bytes to "
+ compressedSize + " bytes, a savings of "
+ (100.0 - 100.0*compressedSize/uncompressedSize) + "%");
}

Anonymous    Jun 01, 1999
Printed
Page 208
Changed "JDK 1.2beta4" to "JDK 1.2" in the second paragraph.

Anonymous    Jun 01, 1999
Printed
Page 210
In the 5th paragraph, "using a the string form" now reads "using

the string form"

Anonymous    Jun 01, 1999
Printed
Page 212
In the output at the top of the page,

"http://metalab.uakom.sk/javafaq/ is up to date"

Now reads:

"http://sunsite.uakom.sk/javafaq/ is up to date"

Anonymous    Jan 01, 2000
Printed
Page 213
In Example 9-15, changed

"Usage: java FileDumper2 [-ahdsilfx] [-little] [-gzip|-deflated] file1...");

to

"Usage: java FileDumper4 [-ahdsilfx] [-little] [-gzip|-deflated] file1...");

Anonymous    Jun 01, 1999
Printed
Page 221
In the top box of Figure 10-1,

MessageDigest md = MessageDigest(getInstance{ algorithm })

Now reads:

MessageDigest md = MessageDigest.getInstance(algorithm)

Anonymous    Jan 01, 2000
Printed
Page 222

The last line of Example 10-1 now reads:

System.out.println(new BigInteger(result));

The output now looks like this:

% java URLDigest http://www.oreilly.com
-24 86 -50 -110 47 -95 12 -95 -36 38 -110 -10 -53 -33 -80 -101 -33 74 -76 41
-135079919537261070114700613868500318745039031255

Anonymous    Jan 01, 2000
Printed
Page 224, 225
The description of the third digest() method on pp. 224-225 was

incorrect. That section was replaced with the following:

"In general, digest algorithms cannot finish the calculation
and return the digest until the last byte is received. When you
are ready to finish the calculation and receive the digest, you
invoke one of three overloaded digest() methods:

public byte[] digest()
public byte[] digest(byte[] input)
public int digest(byte[] output, int offset, int length)
throws DigestException

The first digest() method simply returns the digest as an array
of bytes based on the data that was already passed in through
update(). For example:

byte[] result = sha.digest();

The second digest() method receives one last chunk of data in
the input array, then returns the digest. The third digest()
method calculates the digest and places it in the array output
beginning at offset and continuing for at most length bytes,
then returns the number of bytes in the digest. If there are more
than length bytes in the digest a DigestException is thrown. After
you've called digest(), the MessageDigest object is reset so it
can be reused to calculate a new digest.

Anonymous    Jan 01, 2000
Printed
Page 227
In the output at the top of the page,

"http://metalab.uakom.sk/javafaq/ is up to date"

Should be:

"http://sunsite.uakom.sk/javafaq/ is up to date"

p. 263: In the third code line on this page, it's helpful to add a
test that the password is not the empty string. It doesn't matter for
this application alone, but it will later. So change

if (password != null) {

to

if (password != null && !password.equals("")) {

*** SAFARI BOOKS ONLINE ***

In section 14.1 of Java I/O, " Each Unicode character is a two-byte,
unsigned number with a value between and 65,535." should read " "Each
Unicode character is a two-byte, unsigned number with a value between 0
and 65,535." The zero was omitted. Strangely, the printed book has the zero.

Anonymous   
Printed
Page 228
At the top of the page replaced the first paragraph and line of code

with this (which is accurate as of the release
version of the JDK 1.2)

This returns a string in the form "algorithm Message Digest from provider,
<initialized>" or "algorithm Message
Digest from provider, <in progress>". For example,

SHA Message Digest from SUN, <initialized>

In the above the words "algorithm" and "provider" are italicized.

Anonymous    Jun 01, 1999
Printed
Page 254
Figure 10-3 had the wrong capitalization of GZipOutputStream. It

now reads GZIPOutputStream.

Anonymous    Jan 01, 2000
Printed
Page 255
In the second paragraph, changed "Like all filter stream

constructors, this constructor also takes another input
stream as an argument:" to "Like all filter input stream
constructors, this constructor takes another input stream as an
argument:"

Anonymous    Jun 01, 1999
Printed
Page 257
The first class declaration on the page used to say CipherInputStream

instead of CipherOutputStream. The declaration now reads

public class CipherOutputStream extends FilterOutputStream

In the following paragraph, changed "Like all filter stream constructors,
this constructor also takes another input stream as an argument:" to
"Like all filter output stream constructors, this constructor takes another
output stream as an argument:"

Anonymous    Jun 01, 1999
Printed
Page 284

Used to read:


"version of a class that features and incompatible change"

Now reads:

"version of a class that makes an incompatible change"

Anonymous    Jan 01, 2000
Printed
Page 284
The sentence "The hash() function only depends on the same things

the serialization depends on, so making a compatible change won't change
the SUID." has been deleted.

Anonymous    Jan 01, 2000
Printed
Page 284
The last two sentences on the page ("However, if you do this..."

to "become incompatible.") have been deleted. They have been replaced
with this new paragraph:

"Whether you use a custom SUID or let serialver calculate
one for you, you are responsible for deciding when a change
to a class is compatible with serialization. The serialver
tool does not necessarily generate the same SUID for two
compatible but different classes. Only the prgrammer can
decide whether a new SUID is required."

Anonymous    Jan 01, 2000
Printed
Page 286

The last sentence before Example 11-3 used to read:

"Invocations of the normal ZipFile methods, like entries() or
getInputStream() methods, are merely passed along to the zf
field java.io."

Now reads:

"Invocations of the normal ZipFile methods, like entries() or
getInputStream(), are merely passed along to the ZipFile
field zf."

Anonymous    Jan 01, 2000
Printed
Page 288
In the second paragraph, changed "the virtual machine creates a new

ZipFile object out of thin air" to "the virtual machine creates
a new SerializableZipFile object out of thin air".

Anonymous    Jun 01, 1999
Printed
Page 288
In the last paragraph changed SerializableRandomAccessFile to

SerializableZipFile.

Anonymous    Jun 01, 1999
Printed
Page 291
In the first paragraph in the Preventing Serialization section, a

space was missing after "by throwing a NotSerializableException
from writeObject()." In other words, the last two sentences now read

You can prevent an object from being serialized, even though it or one of
its superclasses implements Serializable, by throwing a
NotSerializableException from writeObject(). NotSerializableException is a
subclass of java.io.ObjectStreamException which is itself a kind of
IOException:

Anonymous    Jun 01, 1999
Printed
Page 291
At the bottom of the page, "throws new NotSerializableException()"

now reads "throw new NotSerializableException()" (both times):

private void writeObject(ObjectOutputStream out) throws IOException {
throw new NotSerializableException();
}

private void readObject(ObjectInputStream in) throws IOException {
throw new NotSerializableException();
}

Anonymous    Jun 01, 1999
Printed
Page 298
In the last paragraph changed "linked list" to "hashtable"

Anonymous    Jun 01, 1999
Printed
Page 299
Example 11-6, the Person class is pretty solidly broken, and

doesn't really do what it claims to do. Here's a fixed version:

import java.util.*;
import java.io.*;

public class Person implements Serializable, ObjectInputValidation {

static Hashtable thePeople = new Hashtable();

String name;
String ss;

public Person(String name, String ss) {

this.name = name;
this.ss = ss;
thePeople.put(ss, name);

}

private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {

in.registerValidation(this, 5);
in.defaultReadObject();

}

public void validateObject() throws InvalidObjectException {

if (thePeople.containsKey(this.ss)) {
throw new InvalidObjectException(this.name + " already exists");
}
else {
thePeople.put(this.ss, this.name);
}

}

public String toString() {
return this.name + " " + this.ss;
}

}

Anonymous    Jun 01, 1999
Printed
Page 306
Changed "cannot be longer than 32 characters" to "cannot be longer

than 31 characters"

Anonymous    Jun 01, 1999
Printed
Page 306
The first three sentences of the first paragraph after the

note are now a little more precise about the requirements of a
Macintosh file name. They now read as follows:

"Read me before you run this program or your hard drive will
get trashed is not a valid Macintosh file name because Mac file
and directory names cannot be longer than 31 bytes. Volume names
cannot be longer than 27 bytes. However, there's no fixed length
to a full path name. The exact number of characters allowed in a
name depends on the number of bytes per character used by the
local encoding. Read me or your HD will be trashed only contains
27 bytes in most encodings and is thus a valid Macintosh file,
directory, and volume name."

Anonymous    Jan 01, 2000
Printed
Page 311
Changed "That's because the MacOS stores a four-letter creator code

in the resource fork of every file" to "That's because the MacOS
stores a four-letter creator code for every file on a disk in the
disk's volume catalog"

Anonymous    Jun 01, 1999
Printed
Page 313
Changed "32 characters long" to "31 characters long"

Anonymous    Jun 01, 1999
Printed
Page 313

At the end of the second paragraph it used to read:

"For example on the Macintosh, a filename can be up to 32
characters long, but a directory name can be no more than 27
characters long." to "For example on the Macintosh, a file or
directory name can be up to 31 bytes long, but a volume name
can be no more than 27 bytes long.".

Anonymous    Jan 01, 2000
Printed
Page 318
In the mini-table in the middle of the page, on the line for the

MacOS has been changed from "html:index.html" to ":html:index.html";
that is add a prefix colon.

Anonymous    Jan 01, 2000
Printed
Page 319
The classpath has been set like this

% java -classpath /home/users/bfrank Trivia

instead of

% java /home/users/bfrank Trivia

The second command line with the relative path is now:

% java -classpath ../bfrank Trivia

instead of

% java ../bfrank/Trivia

Anonymous    Jan 01, 2000
Printed
Page 327

In the second to last paragraph, used to read:

"%202.0% 20Early%20Access%"

Now reads:

"%202.0%20Early%20Access%"

Anonymous    Jan 01, 2000
Printed
Page 338
In the middle of the page, the sentence

"If the directory cannot be created for any other reason,
mkdir()returns false."

has been changed to:

"If the directory cannot be created for any
other reason, including that the directory already existed
before mkdir() was called, mkdir() returns false."

That is, the phrase, "including that the directory already existed before
mkdir() was called" has been added.


Anonymous    Sep 01, 2000
Printed
Page 338
mkdirs() returns true only if it actually creates a

directory. It returns false if all the directories already
exist. Thus the second to last paragraph on the page now reads:

"mkdirs() returns true if some directory in this path did not
already exist and was created, and false if none of them are
created. If mkdirs() returns false, you should first test to see
if the path exists (because it may have existed before you ever
called mkdirs()). If it doesn't exist, then you have to
explicitly test for each directory in the path because the
invocation could have been partially successful."

Anonymous    Sep 01, 2000
Printed
Page 343

In the second paragraph, used to read:


"using the HTMLFilter of Example 12-5"

Now reads:

"using the HTMLFilter of Example 12-6"

Anonymous    Jan 01, 2000
Printed
Page 367
In "getting the list of file filters", the quotation mark at the

end has been replaced with a colon.

Anonymous    Jan 01, 2000
Printed
Page 389
In the footnote, the canonical Unicode reference was

_The Unicode Standard Version 2.0._

It now reads:

The Unicode Standard, Version 2.0.

Anonymous    Jun 01, 1999
Printed
Page 418
In Example 15-1,

for (int i = Character.MIN_VALUE; i < Character.MAX_VALUE; i++) {

Now reads:

for (int i = Character.MIN_VALUE; i <= Character.MAX_VALUE; i++) {

That is, the less than is now a less-than-or-equal-to.

Anonymous    Jan 01, 2000
Printed
Page 429
In the first code fragment, changed

catch (IOexception e) {System.err.println(e);}

to

catch (IOException e) { System.err.println(e); }

Anonymous    Jun 01, 1999
Printed
Page 440-442
The SourceReader program has several bugs. Here's the

corrected version:

package com.macfaq.io;

import java.io.*;

public class SourceReader extends FilterReader {

public SourceReader(InputStream in) {
this(new InputStreamReader(in));
}

public SourceReader(Reader in) {
super(in);
}

private int buffer = -1;

public int read() throws IOException {
if (this.buffer != -1) {
int c = this.buffer;
this.buffer = -1;
return c;
}
int c = in.read();
if (c != '\') return c;
int next = in.read();
if (next != 'u' ) { // This is not a Unicode escape
this.buffer = next;
return c;
}
// read next 4 hex digits
// If the next four chars do not make a valid hex digit
// this is not a valid .java file and you need
// a compiler error
StringBuffer sb = new StringBuffer();
sb.append((char) in.read());
sb.append((char) in.read());
sb.append((char) in.read());
sb.append((char) in.read());
String hex = sb.toString();
try {
return Integer.valueOf(hex, 16).intValue();
}
catch (NumberFormatException e) {
throw new IOException("Bad Unicode escape: \u" + hex);
}
}

private boolean endOfStream = false;
public int read(char[] text, int offset, int length) throws IOException {
if (endOfStream) return -1;
int numRead = 0;
for (int i = offset; i < offset+length; i++) {
int temp = this.read();
if (temp == -1) {
this.endOfStream = true;
break;
}
text[i] = (char) temp;
numRead++;
}
return numRead;
}

public long skip(long n) throws IOException {

char[] c = new char[(int) n];
int numSkipped = this.read(c);
return numSkipped;
}

}

Anonymous    Sep 01, 2000
Printed
Page 470
In the first line of code on the page, changed

public static final NumberFormat getpercentInstance()

to

public static final NumberFormat getPercentInstance()

(that is, an upper case P in percent)

Anonymous    Jun 01, 1999
Printed
Page 497
The parse() method of Example 16-9, ExponentialFormat, now properly

handles all possible exponents. The corrected version reads:

public Number parse(String text, ParsePosition parsePosition) {

int oldIndex = parsePosition.getIndex();

try {
double result = parser.parse(text, parsePosition).doubleValue();
int eposition = text.toUpperCase().indexOf('E');
if (eposition != -1) {
// advance past the E
parsePosition.setIndex(eposition + 1);
// ignore a + sign
if (text.charAt(parsePosition.getIndex()) == '+') {
parsePosition.setIndex(parsePosition.getIndex() + 1);
}
int exponent = parser.parse(text, parsePosition).intValue();
result *= Math.pow(10, exponent);
}
return new Double(result);
}
catch (Exception e) {
parsePosition.setIndex(oldIndex);
return null;
}

}

Anonymous    Jan 01, 2000
Printed
Page 507
The output from the PortOpener program has changed in the release

version. The new output is:

COM1, a serial port, is not currently owned.
COM2, a serial port, is currently owned by Port currently not owned.
LPT1, a parallel port, is not currently owned.
LPT2, a parallel port, is currently owned by Port currently not owned.

Anonymous    Jun 01, 1999
Printed
Page 513
The second row of asterisks has been changed to bold for user input style

Anonymous    Jun 01, 1999
Printed
Page 516-517
The testProperties() method in Example 17-7, PortTester,

now reads:

public static void testProperties(CommPort thePort) {

try {
thePort.enableReceiveThreshold(10);
System.out.println("Receive threshold supported");
}
catch (UnsupportedCommOperationException e) {
System.out.println("Receive threshold not supported");
}

try {
thePort.enableReceiveTimeout(10);
System.out.println("Receive timeout supported");
}
catch (UnsupportedCommOperationException e) {
System.out.println("Receive timeout not supported");
}

try {
thePort.enableReceiveFraming(10);
System.out.println("Receive framing supported");
}
catch (UnsupportedCommOperationException e) {
System.out.println("Receive framing not supported");
}

}

Anonymous    Jan 01, 2000
Printed
Page 520
IN the last code fragment on the page, the & is now a |. That is,

com1.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN
| SerialPort.FLOWCONTROL_RTSCTS_OUT);

Anonymous    Jan 01, 2000
Printed
Page 541
In the text, the title was

_The Unicode Specification 2.0._

It now reads:

The Unicode Standard, Version 2.0.

Anonymous    Jun 01, 1999
Printed
Page 548
The small Greek letter delta (&delta;) is Unicode character

948, not 984. The small letter epsilon (&epsilon;) is Unicode character
949, not 985. Thus the offset of Unicode Greek characters from those in
ISO 8859-7 is 720, not 756. The corrected text now reads:

"For instance, Unicode characters 884 through 1011 encode
the Greek alphabet and associated characters like the Greek
question mark (;). This is a direct transposition by 720 of
characters 128 through 255 of the ISO 8859-7 character set,
which is in turn based on the Greek national standard ELOT
928. For example, the small letter &delta;, Unicode character
948, is ISO 8859-7 character 228. A small &epsilon;, Unicode
character 949, is ISO 8859-7 character 229. In general, the
Unicode value for a Greek character equals the ISO 8859-7
value for the character plus 720."

Note that &epsilon; and &delta; are replaced by the actual Greek
letters.

Anonymous    Jan 01, 2000