Printf and scanf in java – new String formatting features in Java 1.5

1

printf is probably the best known function in C. I did some
programming in C and I didn’t really like it (because I started with C after
quite some experience in Java). But one thing was better than Java, the printf
function. The printf function replaces tokens that start with % with one of the
arguments (usally dynamic values). Strings with dynamic values are more
clarifying and easier to maintain:

printf("I am %d years old",24) versus printf("I am " + 24 +
" years old");

....
 

varargs

Before I start explaining printf you need to know a little
bit about varargs.

One of the reasons the printf function wasn’t possible in
Java was the lack of a method with variable arguments. With the printf function
in C you can pass an arbitrary number of arguments, in Java you had to put
everthing in an array of Objects. And while doing that concatenating a String the old way was shorter and easier.

With Java 1.5 varargs were introduced. The syntax is a bit
odd:

public int sum(int … x){

    int sum=0;

    for(int i=0;
i<x.length; i++){

        sum+=x[i];

    }

    return sum;

}

 

Just add three dots before the name of the variable and
you’re ready. x is now an array of int’s. The type of the variable can be both
native and Object. There are a few restrictions. There can only be one varagrs argument and it should be the last argument in a method.

 

printf

The PrintWriter object has a method printf since Java 1.5.
It works the same as the printf function in C. Let’s show some basic examples:

System.out.print(“%f cm is %f inch”, 2.54, 1F);

Output: 2,540000
cm is 1,000000 inch

%f is used for floats and doubles. Just like C you can
prepend the f with the number of decimals and the precision:

System.out.printf("%9.2f cm is %10d inch\n", 2.54,
1);

System.out.printf("%5.2f cm is %f inch\n", 2.54,
1F);

When the number is smaller than the amount you provided the
output is padded with spaces:

     2,54 cm is          1 inch

 2,54 cm is 1,000000
inch

 

Printf only works on PrintWriter objects. Of course we want
it to work on Strings. Use String.format for the same behaviour as the printf
method. Besides %f there are a lot of characters you can use. These are the
most common:

 

%d

Decimal integers

%f

Decimal numbers

%s

Strings

%%

Escaping for percent sign

 
On http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html#syntax
is a list of other characters you can use.

 

Date format

Another nice thing of the new formatter is date formatting.
Of course we can do that with SimpleDateFormat, but I think that’s too many
lines of code for a simple thing:

Date
date = new Date();

SimpleDateFormat
format = new SimpleDateFormat("dd-MM-yyyy");

String
string = format.format(date);

System.out.println(String.format("The
date: %s", string));

 

To do this with the formatter:

Date
date=new Date();

System.out.println(String.format("The
date: %1$td-%1$tm-%1$tY",date));

 

The syntax might scare you at first sight, but it’s quite
easy.

1$ means pick the first argument, I do this because there is
only one argument and we need three (the date consists of 3 parts). Using an
index of an argument also works without date formatting.

t means pick the time and date formatting characters

d m Y are used for day, month and year padded with 0’s.

For the other characters check:http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html#dt

 

Scanner

The Scanner class works with input. You can specify a
delimiter of tokens (default is a space) and then iterate over the tokens and
put them in the right object type. Example:

String
input = "1 car 2 bike 3 ship";

Scanner
scanner = new Scanner(input);

int a =
scanner.nextInt();

String
b = scanner.next();

int c =
scanner.nextInt();

String
d = scanner.next();

int e =
scanner.nextInt();

String
f = scanner.next();

 

System.out.printf("%d
%s %d %s %d %s", a, b, c, d, e, f);

 

First we create an input string with 3 int’s and 3 Strings.
Then we create a scanner object on that input string. Then we iterate over the
objects and put them in objects with the right type. At then end we reconstruct
the String with printf.

It’s not always safe to use nextInt when there could be a
String (or if you just want to skip all Strings and only save ints. You can use
the hasXxx methods for this. A simple method to get all the ints in a list
would look like this:

public
List<Integer> extractInts(String input) {

    Scanner scanner = new Scanner(input);

    List<Integer> list = new
ArrayList<Integer>();

 

    while (scanner.hasNext()) {

        if (scanner.hasNextInt()) {

            list.add(scanner.nextInt());

        } else {

            scanner.next();

        }

    }

    return list;

}

 

With the useDelimeter method you can change the delimiter of
tokens.

 

Performance

The performance of the new String formatter is slower than
plain string concatenation. I tested a couple of million times with
concatenating 3 Strings of about 100 characters and that was 5 times slower
with String.format(“%s%s%s”,a,b,c);.

The difference between the date format examples is however
only 8% slower (with 3 million tests)

So be careful when you apply the String formatter. It’s
considerably slower. But for logging purposes it’s great.

 

Conlusion

Java 1.5 gives use some new powerful String features.
Unfortunately the performance is a bit disappointing, but maybe in newer
versions of Java the performance will improve. I use the new functions a lot
for logging. The Scanner class is quite new for me, but I expect to use it a
lot.

Share.

About Author

1 Comment

  1. It was good to see your article. Thanks!!
    Oh, and please change conlusion to  conclusion!