braju.com
Java printf & scanf (beta)

com.braju.beta.format
Class FormatReader

java.lang.Object
  |
  +--java.io.Reader
        |
        +--com.braju.beta.io.LookaheadReader
              |
              +--com.braju.beta.io.DataTypeReader
                    |
                    +--com.braju.beta.io.BasicFormatReader
                          |
                          +--com.braju.beta.format.FormatReader

public class FormatReader
extends com.braju.beta.io.BasicFormatReader

Provides formatted output a'la true C-style scanf() with any number of parameters.

In the examples below you will find useful information how to use the class.


Format specification

This is the format of one conversion specification:

% [*] [width] type | set

Field description

* The input will be read as described, but the value read will not be saved anywhere.

width Minimum number of characters (bytes) output.


Width Brief description
n (an integer) A nonnegative integer for the width; e.g. 8.

Precision Brief description
n (an integer) A nonnegative integer for the precision; e.g. 3.

Conversion
type
Corresponding argument
will be printed as
l a logical value, i.e. a boolean will be read into the corresponding parameter. Also support for C-style booleans, i.e. 0 or 1 (<>0). [extension to ANSI-C].
c a character will be read into the corresponding parameter. If width is specified more than one character can read. Then the corresponding parameter should be of type String. Note that even whitespace token will be read. Compare this to the %s-format.
d a decimal integer will be read into the corresponding parameter. Note the difference to %i.
i a decimal integer of any radix (octal, hexadecimal etc.) will be read into the corresponding parameter. Note the difference to %d.
b a binary integer will be read into the correponding parameter. The input can contain either 0b001101 or just 001101. [extension to ANSI-C].
x a hexadecimal integer will be read into the correponding parameter. The input can contain either 0x1eff or just 1eff.
o an octal integer will be read into the correponding parameter. The input can contain either 012727 or just 12727.
e,g a scientific floating point number (e.g. 1.23E-03) or a plain number, decimal or not, will be read into the corresponding parameter.
f a plain number, decimal or not, will be read into the corresponding parameter.
s a string. The corresponding parameter, which should be a String, will contain all consecutive non-whitespace characters on the input starting from the first non-whitespace found. In other words: the next "word" will be read.
n The value of corresponding parameter will be set to the number of tokens read from the input stream this far.
% A single "%" will be read from input and it will not be saved anywhere.

set Brief description
'[' char* ']' A set is string enclosed by square brackets. The set string includes all characters that should be read from the input. If a '^' is followed immediately after the left square bracket it will insted indicate that all characters except those in the set should be read. If the '^' is on another position it will be counted as any other character. To read for instance all characters from a to z the write %[a-z]. To include a ']' or a '-' then place it in the very beginning position in the set-string. E.g. "%[^]-9a-f^]" to read all characters but ']','-','9','a','b',...'f' and '^'.


Example 1.

   Variable name = new StringVariable();
   Variable age  = new IntegerVariable();
   InputStreamReader in0 = new InputStreamReader(System.in);
   FormatReader in = new FormatReader(in0);
   Format.printf("Enter your full name: ");
   in.read(" %[^\n]", new Parameters(name));
   //       ^ you will need this space to tell scanf to
   //         first read all non-whitespace characters.
   Format.printf("Enter your age (in years): ");
   in.read("%i", new Parameters(age));

   Format.printf("Hello %s, you are %i years old.\n",
     new Parameters(name).add(age));

Example 2 (only Java 1.1 and above)

import com.braju.format.*;
public class Person {
  // In Java 1.1 and above we can make use of reflection. To do currPerson you
  // have to put your variables in a PUBLIC class and make them PUBLIC.
  // Note that they can not be hidden inside a method, they have to be
  // attributes.
 
  public String name;
  public int age;
  public FormatReader in;
  public FormatWriter out;
  public Person() {
    // Make use of the predefined in & out in com.braju.format.Format
    // instead of creating your own as we did in the example above.
    in = Format.in;
    out = Format.out;
  }
  public void query() throws Exception {
    out.write("Enter your full name: ");
    // Note that the variable names to FormatReader must be inside quotas,
    // i.e. given as a String. The first parameter tells FormatReader in
    // which object the variables are located. In this case "this".
    in.read(" %[^\n]", new Parameters(this).add("name"));
    out.write("Enter your age (in years): ");
    in.read("%i", new Parameters(this).add("age"));
  }

  public void display() {
    out.write("Hello %s, you are %i years old.\n",
      new Parameters(name).add(age));
  }

  public static void main(String args[]) throws Exception {
    Person currPerson = new Person();
    currPerson.query();
    currPerson.display();
  }
}

Example 3. To read from a file you can do like this

StringVariable name   = new StringVariable();
DoubleVariable points = new DoubleVariable();
DoubleVariable diff   = new DoubleVariable();
FormatReader in = new FormatReader(new FileReader("foo.bar"));
while(!in.isAtEndOfFile()) {
   in.read("%s %f %f\n",
     new Parameters(name).add(points).add(diff));
}

Note that the above examples can be simplified by using the printf & scanf methods defined in com.braju.format.Format.

Since Java only pass parameters by value a work-around is needed. For this reason one need to make use of Variable classes. A Variable class in basically the same thing as standard Java data type-wrapper, such as Integer and Character. The difference is that a Variable can also be set using a set-method. This is not possible in case of the normal data type-wrappers. The naming convension of the Variable classes is to put the string "Variable" after the regular Java data type-wrapper name, e.g. StringVariable, IntegerVariable and CharacterVariable.
Another solution is also available since Java 1.1. The performance is though not as good as in the Variable case. Java reflection does also solve the problem and it is quiet transparent for you as a programmer. One restriction is that you have to have the variables as public attributes, i.e. local variables can not be used. By passing the reference to an object, where you store your attributes, the read-methods will know where to save the values. If you want to, you can use attributes in different objects. Example:

class Dummy {
  public int x;

  private test() {
    Dummy d2 = new Dummy();
    in.read("%d %d\n",
      new Parameters(this).add("x").add(d2).add("x"));
    Format.printf("this.x=%d\nd2.x=%d\n",
      new Parameters(x).add(d2.x));
  }
}
}

Note that if your program are supposed to run under Java1.0.2 you should use com.braju.format.FormatInputStream and com.braju.lang.Variable instead. The procedure is almost the same.

See Also:
Format, Format102, FormatInputStream, Parameters, Variable

Fields inherited from class com.braju.beta.io.DataTypeReader
PERIOD_ANY, PERIOD_COMMA, PERIOD_DEFAULT, PERIOD_DOT, PERIOD_REPLACE
 
Constructor Summary
FormatReader(java.io.Reader in)
           
FormatReader(java.io.Reader in, int sz)
           
 
Method Summary
 void addConversionParser(com.braju.beta.format.ConversionParser cParser)
          Add a new parser for the format string [...].
 void close()
          Closes the stream. [...] The reader should not be used afterwards.
 FormatString compileFormatString(java.lang.String fmt)
          Compile a format string and return the result as a FormatString [...].
static FormatReader conform(java.io.Reader in)
          Always returns an instance of FormatOutputStream wether the input is an instance of that class or not.
 com.braju.beta.format.ConversionParser[] getConversionParsers()
          Gets the conversion parsers.
 boolean getModifyLineSeparators()
          Checks wether the automatic replacement of newlines is turned on or off.
 boolean isAtEndOfFile()
          Checks wether we have reached the end of the input stream or not.
 void mark(int readAHeadLimit)
          Marks the present position in the stream and push it on top of a mark stack [...].
 boolean markSupported()
          Tells whether this stream supports the mark() operation, which it does.
 int read()
          Read a single character [...].
 int read(char[] cbuf)
          Fill the given character array with characters from the reader.
 int read(char[] cbuf, int off, int len)
          Returns whats left in internal buffer or if buffer is empty read directly from stream (this is how Java Core classes works).
 int read(FormatString fmtstr, Parameters parameters)
           
 int read(java.lang.String fmt)
           
 int read(java.lang.String fmt, Parameters parameters)
           
 boolean ready()
          Tells whether this stream is ready to be read.
 void removeConversionParser(com.braju.beta.format.ConversionParser cParser)
           
 void reset()
          Reset the stream to the most recent mark which is popped from the mark stack.
 void resetFormatStringCompiler()
          Resets the internal FormatStringCompiler to the default scanf-format string compiler.
 void setModifyLineSeparators(boolean activated)
          Turns on or off the automatic replacement of all occurenses of newlines ('\r', '\n' and '\r\n') found on the input stream [...].
 long skip(long n)
          Skip the next n characters from the reader.
 
Methods inherited from class com.braju.beta.io.BasicFormatReader
getLastRadix, readNextBinary, readNextBoolean, readNextBoolean, readNextByte, readNextChar, readNextDouble, readNextFloat, readNextHex, readNextInt, readNextLong, readNextLongAnyRadix, readNextNestedQuotation, readNextOctal, readNextQuotation, readNextQuotation, readNextQuotation, readNextScientific, readNextShort, readNextWord, readNextWord
 
Methods inherited from class com.braju.beta.io.DataTypeReader
expandSet, readBinaryDigits, readBinaryDigits, readChar, readCharIgnoreCase, readCharInSet, readCharNotInSet, readChars, readChars, readCharsIgnoreCase, readCharsInSet, readCharsInSet, readCharsNotInSet, readCharsNotInSet, readDigits, readDigits, readHexDigits, readHexDigits, readInteger, readJavaLetters, readJavaLetters, readJavaLettersOrDigits, readJavaLettersOrDigits, readLetters, readLetters, readLettersOrDigits, readLettersOrDigits, readNonWhitespace, readNonWhitespace, readOctalDigits, readOctalDigits, readReal, readReal, readScientific, readScientific, readWhitespace, readWhitespace
 
Methods inherited from class com.braju.beta.io.LookaheadReader
available, currentChar, getCounter, getNbrOfMarks, lookAHead, lookAHeadIgnoreCase, mark, readChar, readLine, resetCounter, toString, unmark
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

FormatReader

public FormatReader(java.io.Reader in)

FormatReader

public FormatReader(java.io.Reader in,
                    int sz)
Method Detail

conform

public static FormatReader conform(java.io.Reader in)
Always returns an instance of FormatOutputStream wether the input is an instance of that class or not.

addConversionParser

public void addConversionParser(com.braju.beta.format.ConversionParser cParser)
Add a new parser for the format string [...]. The new parser is insert first in the queue; the queue is a LIFO-queue. This means that you can always override previously added parsers with a new one. For more information, see FormatStringCompiler.

removeConversionParser

public void removeConversionParser(com.braju.beta.format.ConversionParser cParser)

resetFormatStringCompiler

public void resetFormatStringCompiler()
Resets the internal FormatStringCompiler to the default scanf-format string compiler.

getConversionParsers

public com.braju.beta.format.ConversionParser[] getConversionParsers()
Gets the conversion parsers.

compileFormatString

public FormatString compileFormatString(java.lang.String fmt)
Compile a format string and return the result as a FormatString [...]. It is recommended to use this method if the same format string will be used several times.
When the format string is parsed, all conversion parsers, starting with the first, is asked if they are "interrested" (trigged by) the current character. If one conversion parser's answer is yes, then that parser start parsing the string. If the parsing succeed a FormatString is returned, otherwise next "interrested" parser gets its turn. If now conversion parser succeed to parser from the current character, no characters are read, and then null is returned. No exception is thrown.

read

public int read(FormatString fmtstr,
                Parameters parameters)
         throws ParseException,
                java.io.IOException,
                java.lang.IllegalAccessException

read

public int read(java.lang.String fmt,
                Parameters parameters)
         throws ParseException,
                java.io.IOException,
                java.lang.NoSuchFieldException,
                java.lang.IllegalAccessException

read

public int read(java.lang.String fmt)
         throws ParseException,
                java.io.IOException,
                java.lang.NoSuchFieldException,
                java.lang.IllegalAccessException

getModifyLineSeparators

public boolean getModifyLineSeparators()
Checks wether the automatic replacement of newlines is turned on or off.
Overrides:
getModifyLineSeparators in class com.braju.beta.io.LookaheadReader

setModifyLineSeparators

public void setModifyLineSeparators(boolean activated)
Turns on or off the automatic replacement of all occurenses of newlines ('\r', '\n' and '\r\n') found on the input stream [...]. If a newline is found it is changed with a '\n' if the automatic replacement is turn on. This property is by default activated.
Overrides:
setModifyLineSeparators in class com.braju.beta.io.LookaheadReader

isAtEndOfFile

public boolean isAtEndOfFile()
                      throws java.io.IOException
Checks wether we have reached the end of the input stream or not.
Overrides:
isAtEndOfFile in class com.braju.beta.io.LookaheadReader

close

public void close()
           throws java.io.IOException
Closes the stream. [...] The reader should not be used afterwards.
Overrides:
close in class com.braju.beta.io.LookaheadReader
Throws:
java.io.IOException - if an I/O error occurs

mark

public void mark(int readAHeadLimit)
Marks the present position in the stream and push it on top of a mark stack [...]. Subsequent calls to reset() will attempt to reposition the stream to this point. If the mark stack is full, nothing will happen.
Overrides:
mark in class com.braju.beta.io.LookaheadReader
Parameters:
readAHeadLimit - This parameter is actually not used.

markSupported

public boolean markSupported()
Tells whether this stream supports the mark() operation, which it does.
Overrides:
markSupported in class com.braju.beta.io.LookaheadReader

read

public int read()
         throws java.io.IOException
Read a single character [...]. This method will block until a character is available, an I/O error occurs, or the end of the stream is reached.
Overrides:
read in class com.braju.beta.io.LookaheadReader
Returns:
The character read, as an integer in the range 0 to 16383 (0x00-0xffff), or -1 if the end of the stream has been reached the next available character or (char)-1 if there is no more characters available.
Throws:
java.io.IOException - if an I/O error occurs

read

public int read(char[] cbuf)
         throws java.io.IOException
Fill the given character array with characters from the reader.
Overrides:
read in class com.braju.beta.io.LookaheadReader
Returns:
the number of characters actually read.
Throws:
java.io.IOException - if an I/O error occurs

read

public int read(char[] cbuf,
                int off,
                int len)
         throws java.io.IOException
Returns whats left in internal buffer or if buffer is empty read directly from stream (this is how Java Core classes works).
Overrides:
read in class com.braju.beta.io.LookaheadReader
Returns:
number of characters actually read.
Throws:
java.io.IOException - if an I/O error occurs

ready

public boolean ready()
              throws java.io.IOException
Tells whether this stream is ready to be read. A look ahead character stream is ready if the buffer is not empty, or if the underlying character stream is ready.
Overrides:
ready in class com.braju.beta.io.LookaheadReader

reset

public void reset()
Reset the stream to the most recent mark which is popped from the mark stack.
Overrides:
reset in class com.braju.beta.io.LookaheadReader

skip

public long skip(long n)
          throws java.io.IOException
Skip the next n characters from the reader.
Overrides:
skip in class com.braju.beta.io.LookaheadReader
Returns:
the number of characters actually skipped.
Throws:
java.io.IOException - if an I/O error occurs

braju.com
Java printf & scanf (beta)

Copyright 1997-2000, Henrik Bengtsson.