Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
The two types of streams are organized into two separate class hierarchies, one consisting entirely of the byte-oriented stream
classes, and the other consisting entirely of character-oriented stream classes. The classes within the two hierarchies are
named consistently, except for their suffix. The byte-oriented stream classes end in either InputStream or OutputStream, while the character-oriented stream classes end in either Reader or Writer. The two hierarchies are functionally almost identical, and they contain most of the same subclass specializations (for example,
one contains LineNumberInputStream and the other contains LineNumberReader).
Prior to version 1.1, the Java class library provided only byte-oriented streams. This setup reflected the reality imposed by the operating systems on which Java was developed -- they were hopelessly byte-oriented, and Java was initially tailored with that environment in mind. The byte-oriented stream classes, however, were flawed in one area -- support for Java's highly regarded Unicode character encoding. As you will soon learn, these classes provided little or no support for converting between bytes and characters.
Unicode is an international multi-language character encoding standard. Most operating systems we are familiar with use ASCII (American Standard Code for Information Interchange) encoding. ASCII (with a 7-bit, 128-character set) doesn't do a very good job supporting characters from languages similar to ours (Danish, for example), much less the character sets for languages such as Japanese or Thai. By basing its character encoding on Unicode (with a 16-bit, 65,536-character set) instead of ASCII, Java supposedly solved that problem -- or did it?
PrintStream, a byte-oriented subclass of OutputStream, and the class from which the objects System.out and System.err are constructed.The PrintStream class provides a bevy of methods for printing Java primitive data types and objects to an output stream. These are the two
most obvious:
public void println(char [] rgc); public void println(String str);
Here are their implementations:
/**
* Prints an array of characters.
* @param s the array of chars to be printed
*/
synchronized public void print(char s[]) {
for (int i = 0 ; i < s.length ; i++) {
write(s[i]);
}
}
/**
* Prints a String.
* @param s the String to be printed
*/
synchronized public void print(String s) {
if (s == null) {
s = "null";
}
int len = s.length();
for (int i = 0 ; i < len ; i++) {
write(s.charAt(i));
}
}
Both methods call write, which, according to the specification, writes a byte (the low eight bits of its integer argument). Specifically, the documentation
states that the println(char [] rgc) method prints "the low eight bits of each of the characters in the character array, followed by a newline character, to this
print stream's underlying output stream."
Likewise, for the method println(String str) the documentation notes that "if the string argument is null, the string "null" followed by a newline character is printed
to this print stream's underlying output stream. Otherwise, the low eight bits of each of the characters in the string, followed
by a newline character, is printed to the underlying output stream."
Wack! These two methods crop a Unicode character right back down to ASCII! Since byte-oriented streams were all the class library supplied, proper support for Unicode was cut off well below the knees. An unfortunate decision, I suppose, but one that probably made sense given (as I mentioned earlier) the byte-oriented nature of the operating system on which Java was developed.
So the Java developers at Sun created a new set of character-oriented stream classes called Readers and Writers.
Common character-oriented input stream methods
Let's take a look at the methods common to all character-oriented input streams (or readers). Following each method declaration,
I'll list the tasks the method performs.
public int read() throws IOException
IOException if an error occurs during the read operation.
public int read(char [] rgc) throws IOException
IOException if an error occurs during the read operation.
public int read(char [] rgb, int nOff, int nLen) throws IOException
IOException if an error occurs during the read operation.
public long skip(long n) throws IOException
IOException if an error occurs during the skip operation.
public boolean ready() throws IOException
IOException if an error occurs during the operation.
public void close() throws IOException
IOException if an error occurs during the operation.
public void mark(int nReadLimit)
reset() will reposition the input stream to this position.
public void reset() throws IOException
IOException if the stream has not been marked, or if the mark has been invalidated.
public boolean markSupported()
Common character-oriented output stream methods
Let's take a look at the methods common to all character-oriented output streams (or writers). As with the previous section,
I'll list the tasks the method performs following each method declaration.
public void write(int c) throws IOException
IOException if an error occurs during the write operation.
public void write(char [] rgc) throws IOException
IOException if an error occurs during the write operation.
public void write(char [] rgc, int nOff, int nLen) throws IOException
IOException if an error occurs during the write operation.
public void write(String str) throws IOException
IOException if an error occurs during the write operation.
public void write(String str, int nOff, int nLen) throws IOException
IOException if an error occurs during the write operation.
public void flush() throws IOException
IOException if an error occurs during the operation.
public void close() throws IOException
IOException if an error occurs during the operation.
Reader and Writer classes in place of the InputStream and OutputStream classes. Consequently, this code only works with version 1.1 of the Java language.Let's take a brief look at how the program works.
The centerpiece of the program is the class PatternFilter. This class is derived from class FilterReader.
public int read() throws IOException
{
// Look ahead in the input stream for a match --
// method test() should throw an exception is one
// one is found...
test();
return in.read();
}
The read method first tests the input stream for a pattern match and then (if the test doesn't fail) returns a single character. The
test method must be implemented in a subclass, and StringPatternFilter is just such a subclass.
protected void test() throws IOException
{
// Read characters, create a string, and
// compare.
in.mark(_l);
char [] rgc = new char [_l];
in.read(rgc);
in.reset();
String str = new String(rgc);
if (str.equals(_str))
{
throw new JunkMailException(_str);
}
}
The test method marks the current position in the stream, which allows the method to rewind the stream to that position once the test
is completed. It then checks for an exact match to the pattern string. If the strings match, test throws an exception; otherwise, it quietly returns.
The class Main builds a list of these filters and connects them to the system input stream System.in.
To accommodate as many of you as possible, I've bundled the code as both a gzipped tar file and a zip file.
Like last month's code, this code doesn't run as an applet, so you'll need access to the Java Development Kit or a similar command-line environment. Once you get the code, unpack it in a convenient location.
Next, from the command line, execute the Java runtime as follows:
% java Main [keyword] [keyword] ... < [email file]
You may specify any number of keywords on the command line. The program builds a filter for each of the keywords and links the filters together -- into a stream. The input is expected to arrive on standard input. The program will read from standard input, send the data through the stream, and write to standard output. If any of the filters detect a match on their keyword, they will raise an exception, which will stop the program.
See you next month.
Reader class for Java 1.1 http://www.javasoft.com/products/jdk/1.1/docs/api/java.io.Reader.html
Writer class for Java 1.1 http://www.javasoft.com/products/jdk/1.1/docs/api/java.io.Writer.html
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq