Reading textual data: Fun with
streams - JavaWorld - April 1999
Tutorial Details:
Reading textual data: Fun with streams
Reading textual data: Fun with streams
By: By Merlin Hughes
Find out how to extend and customize the character-stream classes to easily read textual data
ever let it be said that I'm happy to rush out a simple article (or book) just to meet a publisher's deadline. What started out as a basic, inefficient character-stream filter, designed to read a stream of digits and parse it into a number, has gradually ballooned into a small stream library sporting unnecessary features and go-faster stripes. Not only has the evolving character-stream library discarded many genetically-inferior siblings along the way, it's behind schedule! (This brings back memories of that 300-page manuscript I discarded in favor of starting anew. I think I'm beginning to see a destructive pattern emerging...)
I initially set out to design a data-reading character-stream filter class. Analogous to the byte-stream filter DataInputStream , this character-stream filter was intended to provide the capability to read textual data from a character stream (namely the output of a human or the PrintWriter println() method).
Let me now, in retrospect, describe what I actually implemented.
First, I created an UndoReader class. This character-stream filter supports three special methods:
checkpoint()
commit()
rollback()
As you read characters through the stream, you have the option to checkpoint the stream -- that is, save the stream's current state and put it into a mode such that it stores all data subsequently read through it. From that point on, the UndoReader stores all the data you read. After any amount of reading, choosing to commit the stream will cause the stored data to be discarded, after which reading proceeds undisturbed. Alternatively, choosing to rollback the stream will cause it to rewind and revert to reading from the position at which you asserted the checkpoint -- just as if you hadn't yet read anything. This stream also supports a couple of related methods.
Next, I implemented the DataReader class, the character-stream filter. This class makes use of the UndoReader class and provides methods to read all the primitive Java types ( readInt() , readFloat() , readBoolean() , and so on). What is special about this class is that if you attempt to read a primitive from the stream and it turns out the stream data is incorrect -- if, for example, you attempt to read a Boolean and the next token in the stream is truthfulness -- it rolls back, un-reading any characters read during the erroneous operation, and throws an exception. The stream also supports a feature whereby it can read data one line at a time, signaling each time the end of a line is reached (among other wonders).
The classes I developed will only work in JDK 1.1-plus. Adapting them to work as InputStream s, usable under JDK 1.0.2, should be quite easy, however.
Justification for UndoReader
In the interest of brevity, I'll spare you an introduction to character streams . Todd Sundsted's November 1997 How-To Java column should serve that purpose quite adequately; if you want an introduction to byte streams , check out Todd's October 1997 column. For further details of the Java stream classes, I refer you to Java Network Programming, Second Edition, which I coauthored with Michael Shoffner and Derek Hamner, and which is due out any day now. (See Resources .)
What I should perhaps explain is my justification for the UndoReader class. At the most abstract level, I want the ability to undo a series of read operations, because otherwise my DataReader class will violate the basic law of propriety: It would be improper for an erroneous attempt at reading an int to end up consuming a Boolean . Furthermore, the behavior of my class wouldn't necessarily be clearly defined in the presence of such an error: the amount of erroneous input consumed would be implementation-dependent, and exposing implementation-dependent details of this nature simply invites abuse.
Those readers familiar with the stream classes may then ask about the mark() and reset() methods, or indeed the PushbackReader class: Do these basic features of the stream API not already address my needs? Indeed, use of the mark() and reset() methods does allow a sequence of read operations to be undone, and the PushbackReader unread() methods can be used to the same effect. However, both of these options are bounded. Therefore you must, in each case, declare ahead of time the maximum volume of data you will un-read. In our situation, no such limit exists for textual data: "00...01" is a valid integer, just as "00...0z" is not. I cannot, simply to avoid writing an extra class, presume to impose arbitrary limitations on the data I will process.
Thus rationalized, we can now proceed with the code.
Class UndoReader
The UndoReader class is a character-stream filter that provides unbounded checkpoint, commit, and rollback operations and an additional undo facility.
Figure 1. Using methods checkpoint(), commit(), rollback(), and undo()
When checkpoint() is used, it proceeds to store all data read through it in an internal, expanding buffer
When commit() is used, the stored contents of the checkpoint buffer are discarded and further reads are no longer stored
When rollback() is used, reading reverts to data stored in the internal buffer; when this is used up, reading proceeds as normal
Any number of reads performed since a checkpoint can be undone without a full rollback by partially reverting in the internal buffer
It is an error to checkpoint a stream that has already been checkpointed or to commit, rollback, or undo a noncheckpointed stream
We must support the case where a checkpoint is placed while we're still reading out of the internal buffer
The class definition
We'll start by looking at our class definition:
package org.merlin.io;
import java.io.*;
public class UndoReader extends Reader {
protected static final int INITIAL_UNDO_SIZE = 64;
protected Reader reader;
protected int[] buffer;
protected int index, stored, capacity;
protected boolean storing, restoring, closed;
public UndoReader (Reader reader) {
this (reader, INITIAL_UNDO_SIZE);
}
public UndoReader (Reader reader, int capacity) {
super (reader);
this.reader = reader;
this.capacity = capacity;
buffer = new int[capacity];
}
...
}
Ordinarily, a character-stream filter would inherit from FilterReader ; however in this case we must override the entire function of the Reader superclass so FilterReader will be of no benefit.
The constructors we provide allow the attached stream, and optionally the initial buffer capacity, to be specified. As the internal buffer can grow as necessary, this will only affect efficiency. In the constructor, we initialize the buffer variable, in which checkpoint data are stored, and the capacity variable, which defines the current size of our buffer.
You may notice that the checkpoint buffer is, in fact, an int array and not a char array. The reason: I wish to be able to store not only normal character data, but the end of file (EOF) [-1] in this buffer. Although there may be other ways to implement this, my purpose is served by this solution.
Other variables related to this buffer are stored , for the amount of checkpoint data that have been stored; and index , for the current read index when data are read from the buffer. The storing flag indicates that a stream has been checkpointed, so data should be stored in the checkpoint buffer; restoring indicates a rollback, so data should be read from the checkpoint buffer; and closed indicates the stream has been closed.
Figure 2. Internals of the UndoReader class
The read() methods
We now look at the operation of reading a single character:
public int read () throws IOException {
synchronized (lock) {
int result;
if (!storing && !restoring) {
result = reader.read ();
} else if (restoring) {
result = buffer[index ++];
if (index >= stored)
restoring = false;
} else {
result = reader.read ();
if (stored + 1 > capacity)
ensureCapacity (1);
buffer[stored ++] = result;
}
return result;
}
}
protected void ensureCapacity (int amount) {
capacity = capacity * 2 + amount;
int[] copy = new int[capacity];
System.arraycopy (buffer, 0, copy, 0, index);
buffer = copy;
}
We start by synchronizing on lock . This variable, inherited from the superclass, is the attached stream ( reader ) we passed to the superconstructor. It is more efficient for us to synchronize on reader than on this , because if we subsequently call synchronized methods on the attached stream, those synchronization calls will not incur any significant costs.
Figure 3. Synchronization efficiency
If we have neither placed the stream in the checkpoint buffer nor rolled it back, we can simply read a character from the attached stream. Otherwise, if we have rolled it back, we must return a character from the internal checkpoint buffer. If we then reach the end of the internal buffer, we can reset restoring . Otherwise, the stream has been checkpointed, so we must read a character from the attached stream and store it in the checkpoint buffer.
Before inserting data into the checkpoint buffer, we use the ensureCapacity() method to enlarge the array to hold the extra datum. Whenever we perform this enlargement, we more than double the buffer's size. This means it will grow very rapidly to accommodate our needs. (It could, for instance, grow from 1 byte to 1 megabyte in just 20 expansions.)
Read multiple characters in one call:
public int read (char[] dst, int offset, int length) throws IOException {
synchronized (lock) {
int result;
if (!storing && !restoring) {
result = reader.read (dst, offset, length);
} else if (restoring) {
if (buffer[index] < 0) {
result = buffer[index ++];
} else {
result = (length < stored - index) ? length : stored - index;
for (int i = 0; i < result; ++ i)
dst[offset + i] = (char) buffer[index ++];
}
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Reading textual data: Fun with
streams - JavaWorld - April 1999
View Tutorial: Reading textual data: Fun with
streams - JavaWorld - April 1999
Related
Tutorials:
|
Displaying 1 - 50 of about 253 Related Tutorials.
|
Java Interview Questions - Page 11
;
Answer: The
ObjectInputStream class supports the reading of objects from input streams.
Question: How are this() and super() used |
Writing and reading from/to a serialized file through Hash Table in Java
Writing and reading from/to a serialized file through
Hash Table in Java
Writing and reading from/to a serialized file through
Hash...("Closing all output streams...\n");
  |
Reading Request Information
Reading Request Information
Reading Request Information
  |
Java error reading from file
java error reading from file
Java error reading...;
Java error reading file...
In this Tutorial we help you in understanding a n example from Java error
reading |
Reading Request Information
|
Use of PreferenceStore class
values to the files or streams and to load the default values from the file or
streams.
The method setDefault(String name, String value) sets the default
value |
Java I/0 Examples
. Java InputStream is
defined for reading the stream, byte stream and array of byte stream.
Classes and Interfaces of the I/O Streams... in the given table.
Reading Text from |
Reading And Writing Excel File
How we can pass various data types into cell in an excel sheet using jsp
reading and writing excel file... that it is used to read
the excel file. After reading the excel file we use write() method |
Reading RDF file in Java
Reading RDF file in Java
Reading RDF file in Java
  |
Reading File into ByteArray
Reading File into ByteArray
Reading File into ByteArray
  |
Reading XML from a File
XML,XML Tutorials,Online XML Tutorial,XML Help Tutorials
Reading XML from a File
 ... for reading XML from a file are described below :-
File f = new File(" |
Reading a File into a Byte Array
Java Read File into Byte Array,Read File into Byte Array Java,Array Program in Java
Reading a File into a Byte Array
  |
Reading an XML document using JDOM
Reading an XML document using JDOM, XML,XML Tutorials,Online XML Tutorial,XML Help Tutorials
Reading an XML document using JDOM... used in code given below for
reading an XML document using JDOM:-
SAXBuilder |
Reading XML Data from a Stream
Reading XML Data from a Stream, XML,XML Tutorials,Online XML Tutorial,XML Help Tutorials
Reading XML Data from a Stream... are some of the methods used in code given
below for Reading XML Data |
Reading Lines from a String Using a Regular Expression
Reading Lines from a String Using a Regular Expression
Reading Lines from a String Using a Regular Expression... given in the section for the best illustration of
the procedure of reading |
Reading ISO Latin-1 Encoded Data in Java
Read Encoded Latin,Reading ISO Latin-1 Encoded Data in Java
Reading ISO Latin-1 Encoded Data in Java
 ... for
reading contents from the specified file in standard ISO-1 format using
the " |
Reading UTF - 8 Encoded Data in Java
Java UTF8,Read UTF 8,Read UTF8 in Java,Reading UTF-8 Encoded Data
Reading UTF - 8 Encoded Data in Java
 ...;
Introduction
It supports standard UTF-8 when reading and
writing strings through |
Making Tokens of a Java Source Code
in understanding Java programming in the most
simplest way. Here after reading this lesson...
,after reading a file we need to generate a tokens
out of that file so, we use |
Making Tokens of a Java Source Code
. Now we need to read the file so that we can use FileReader class
,After reading |
Java - Read file Applet
of the reading file from an applet. This
program illustrates you how an applet can read |
Java Read File Line by Line - Java Tutorial
be read by a data input stream.
Data input streams and data output streams represent... as to provide for the efficient reading of characters, arrays, and
lines.
The buffer....
Programs that use DataInputStreams for textual input
can be localized by replacing |
Getting The XML Root Element
;
After reading this section |
GPS Terminology
;
Here are some of the most common words that you will come across while reading |
JSDAI
;
JSDAI? is an Application Programming Interface (API) for reading, writing |
Java read file line by line - Java Tutorial
DataInputStreams for
reading textual input line by line with an appropriate
BufferedReader...;
Introduction
Lets understand some I/O streams that are used to
perform reading and writing operation in a file. In the section of Java Tutorial you |
Read Text from Standard IO
package. It acts as an abstract
class for reading character streams...
Reading Text from the Standard Input,Java Read from Standard Input - Java I/O Tutorials
Reading Text from the Standard |
Java I/0 Examples
. Java InputStream is
defined for reading the stream, byte stream and array of byte stream.
Classes and Interfaces of the I/O Streams... in the given table.
Reading Text from |
How to make a blooming Face.
am sure that you can design as
you want by reading this tutorial.
Open A Picture |
Struts 2 Date Examples
available in the Struts 2 Framework. After reading the tutorials
you will lean how |
Struts 2 Date Examples
available in the Struts 2 Framework. After reading the tutorials
you will lean how |
What is Java I/O?
are used for reading from and writing to byte
streams, respectively... class
is used for reading the data such as a byte and array of bytes... the programming interface for all input streams that are inherited
from |
Definition of Bioinformatics
deciphered! In other words, scientists have succeeded in reading the chain of
more |
Multiple Value initialization and retrieval by put and get method
out the flow of using put and get
method of the preferences. After reading |
Counter in Init() Method
and by
reading the init parameter to know from where the counting will begin.
In this program |
Java - Read file Applet
of the reading file from an applet. This
program illustrates you how an applet can read |
Open Source FTP
reading some of the comments for the blog entry, OK is pretty much accurate. I |
Linux Books
is to explain the use of the GNU C and C++ compilers, gcc and g++. After reading... places (see section Further reading).
Experienced programmers who |
Spoon JDT
,
methods, fields, statements, expressions...) can be accessed both for reading |
Summary: I/O
()
Should close when finished reading.
BufferedWriter Methods
voidbw.writeLine...);
}
Copyright 1999 Fred Swartz
Last update: 2000-02-30 |
Convert Image Formats
streams, serialization and the file system.
Classes ImageReader....ImageIO for reading
and writing the images respectively. The class... are reading the image from system by
using read() method of ImageIO |
Zip File Using Java
(such as image data), for reading streams of characters by considering
FileReader |
Changes in I/O
is newly added in JAVA SE 6.
Reading passwords without echoing their text
JAVA SE... to the Standard Streams. Its a single, predefined object of Console type that provide most of the same features as by Standard Streams, and others besides. The Console |
Using a Random Access File in Java
in a
sequential but Unlike the input and output streams java.io. RandomAccessFile
is used for both reading and writing files A random access file
treats with a large array... where the reading or writing operation
has to be done.
Random AccessFile implements |
Zip Folder Using Java
to read stream of
row bytes such as image data, for reading streams of characters |
Summary: Methods
Copyright 1999 Fred Swartz |
Open Source Business Model
not generate stable and scalable revenue
streams. In actuality, in the 21st... 1999, eZ systems has been creating Open Source software and serves its customers... source business model
On December 1999, Matra Datavision announced the adoption |
Transforming XML with SAXFilters
is a convenience class for reading character files. it is generally meant for
reading streams of characters.
CustomFilter filter = new CustomFilter():-creates a
custom |
Console I/O
the debugging phase.
Console I/O streams
There are three predefined I/O streams..., and output streams.
System.in // an InputStream.
System.out |
Python Programming Books
of you make donations each month (out of about a thousand of you reading the text...://diveintopython.org/. If you're reading it somewhere else, you may not have the latest version... changes that have taken place since the release of the first edition in 1999 |
mediniQVT
in the
textual concrete syntax of the Relations language
Trace management |
|
|
|