Title: printf, sprintf
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

printf and sprintf features

This is for all of you fans of C/C++ who learned printf and sprintf and wonder how to do this in Java.

The good news is that Java provides a package called java.text which has tons of flexibility to work with any international way of displaying anything.

The bad news is that it is a whole lot more difficult to do than simple printf/sprintf stuff.

Most Java people don't worry about text output that much. Java has always focused on GUI approaches, and making System.out.println do most of the things that you want to do easily.

However, System.out.println doesn't have features that printf/sprintf have always had:

- Specify the size of a field
- Specify the precision used
- Specify whether your data is left justfied or right justified.

After digging a little, I found and modified some software that gives you printf/sprint --- not quite as convenient as the vintage versions. It uses the NumberFormat class in the java.text package.

The main routines are provided to show you how to use the classes.

Sprintf.java


import java.text.*;

public class Sprintf {
  public static final int LEFT=1;
  public static final int RIGHT = 2;

  private static int MAX_WIDTH = 40;
  private static final String spaces = buildPadding (MAX_WIDTH, ' ');
  private static final String zeros = buildPadding(MAX_WIDTH, '0');
  private String padding = spaces;
  private int width = 0;
  private int justify = RIGHT;
  private final String endLine = System.getProperty("line.separator");

  // -1 means use max precision
  private int decimalPlaces = -1;
  // used in trimming decimal digits
  private NumberFormat form = NumberFormat.getInstance();

  public void setWidth(int width)
  {
    if (width < 0)
        this.width = 0;
    else if (width > MAX_WIDTH)
        this.width = MAX_WIDTH;
    else
        this.width = width;
   }

   public void  setDigits(int places){
      decimalPlaces = places;
      form.setMaximumFractionDigits(decimalPlaces);
   }

   public void setJustify (int leftOrRight) {
      if (leftOrRight == LEFT || leftOrRight == RIGHT)
         justify = leftOrRight;
   }

   public void setPadChar(char pad){
        if (pad == ' ') padding = spaces;
        else if (pad == '0') padding = zeros;
        else padding = buildPadding(MAX_WIDTH, pad);
   }

   public String sprintf(String s){
        if (s.length() >= width)
            return s;
        else if (justify == LEFT)
            return (s + padding.substring(0, width - s.length()));
        else return (padding.substring(0, width - s.length()) + s);
    }
    public String sprintf(boolean value){
        return sprintf(String.valueOf(value));
    }
    public String sprintf(char value){
        return sprintf(String.valueOf(value));
    }
    public String sprintf(char[] value){
        return sprintf(String.valueOf(value));
    }
    public String sprintf(int value){
        return sprintf(String.valueOf(value));
    }
    public String sprintf(long value){
        return sprintf(String.valueOf(value));
    }
    public String sprintf(Object value){
        return sprintf(String.valueOf(value));
    }
    public String sprintf(double value){
        return sprintf(trimDigits(String.valueOf(value)));
    }
    public String sprintf(float value){
        return sprintf(trimDigits(String.valueOf(value)));
    }

    public String sprintfln(){
        return endLine;
    }

    private String trimDigits(String value){
        int places, pos, exp;
        String needsRounding;

        if (decimalPlaces == -1)
            return value;
        pos = value.indexOf(".");
        exp = value.indexOf("E");
        if (exp == -1)
            places = value.length() - pos -1;
        else
            places = exp - pos -1;
        if (places < decimalPlaces)
            return value;

        if (exp == -1)
            needsRounding = value;
        else needsRounding = value.substring(0, exp);
        if (exp == -1)
            return round (needsRounding);
        else
            return round (needsRounding) + value.substring(exp);
    }

    private String round (String s){
        String str = form.format(Double.parseDouble(s));
        return str;
    }

    private static String buildPadding(int width, char pad)
    {
        StringBuffer sbuf = new StringBuffer(width);
        for (int i = 0; i < width; i++)
            sbuf.append(pad);
        return sbuf.toString();
    }

  public static void main (String[] args){
    int x =19876;
    double  y =22.123456789;
    double z = 4.5678E-20;

    Sprintf sformat= new Sprintf();
    sformat.setWidth(10);
    sformat.setDigits(2);

    System.out.print(   sformat.sprintf("col1"));
    System.out.print(   sformat.sprintf("col2"));
    System.out.print(   sformat.sprintf("col3"));
    System.out.print(   sformat.sprintfln());

    System.out.print(   sformat.sprintf(x));
    System.out.print(   sformat.sprintf(y));
    System.out.print(   sformat.sprintf(z));
    System.out.print(   sformat.sprintfln());

    // Or equivalently
    System.out.println("****** Using a StringBuffer ****");
    StringBuffer sb = new StringBuffer();

    sb.append(   sformat.sprintf("col1"));
    sb.append(   sformat.sprintf("col2"));
    sb.append(   sformat.sprintf("col3"));
    sb.append(   sformat.sprintfln());

    sb.append(   sformat.sprintf(x));
    sb.append(   sformat.sprintf(y));
    sb.append(   sformat.sprintf(z));
    sb.append(   sformat.sprintfln());

    System.out.print(sb);
  }


}


FormattedWriter.java



import java.io.*;
import java.text.*;

public class FormattedWriter extends PrintWriter{
  public static final int LEFT=1;
  public static final int RIGHT = 2;

  private static int MAX_WIDTH = 40;
  private static final String spaces = buildPadding (MAX_WIDTH, ' ');
  private static final String zeros = buildPadding(MAX_WIDTH, '0');
  private String padding = spaces;
  private int width = 0;
  private int justify = LEFT;

  // -1 means use max precision
  private int decimalPlaces = -1;
  // used in trimming decimal digits
  private NumberFormat form = NumberFormat.getInstance();


  public FormattedWriter(OutputStream os){
     super(os, true); // make default auto-flushing
  }
  public FormattedWriter(FileWriter writer){
    super(writer, true);
  }
  public FormattedWriter(String filename) throws java.io.IOException
  {
    this(new FileWriter(filename));
  }

  public void setWidth(int width)
  {
    if (width &lt; 0)
        this.width = 0;
    else if (width &gt; MAX_WIDTH)
        this.width = MAX_WIDTH;
    else
        this.width = width;
   }

   public void  setDigits(int places){
      decimalPlaces = places;
      form.setMaximumFractionDigits(decimalPlaces);
   }

   public void setJustify (int leftOrRight) {
      if (leftOrRight == LEFT || leftOrRight == RIGHT)
         justify = leftOrRight;
   }

   public void setPadChar(char pad){
        if (pad == ' ') padding = spaces;
        else if (pad == '0') padding = zeros;
        else padding = buildPadding(MAX_WIDTH, pad);
   }

   public void printf(String s){
        if (s.length() &gt;= width)
            super.print(s);
        else if (justify == RIGHT)
            super.print(s + padding.substring(0, width - s.length()));
        else super.print(padding.substring(0, width - s.length()) + s);
    }
    public void printf(boolean value){
        printf(String.valueOf(value));
    }
    public void printf(char value){
        printf(String.valueOf(value));
    }
    public void printf(char[] value){
        printf(String.valueOf(value));
    }
    public void printf(int value){
        printf(String.valueOf(value));
    }
    public void printf(long value){
        printf(String.valueOf(value));
    }
    public void printf(Object value){
        printf(String.valueOf(value));
    }
    public void printf(double value){
        printf(trimDigits(String.valueOf(value)));
    }
    public void printf(float value){
        printf(trimDigits(String.valueOf(value)));
    }

    public void printfln(){
        println();
    }

    private String trimDigits(String value){
        int places, pos, exp;
        String needsRounding;

        if (decimalPlaces == -1)
            return value;
        pos = value.indexOf(".");
        exp = value.indexOf("E");
        if (exp == -1)
            places = value.length() - pos -1;
        else
            places = exp - pos -1;
        if (places &lt; decimalPlaces)
            return value;

        if (exp == -1)
            needsRounding = value;
        else needsRounding = value.substring(0, exp);
        if (exp == -1)
            return round (needsRounding);
        else
            return round (needsRounding) + value.substring(exp);
    }

    private String round (String s){
        String str = form.format(Double.parseDouble(s));
        return str;
    }

    private static String buildPadding(int width, char pad)
    {
        StringBuffer sbuf = new StringBuffer(width);
        for (int i = 0; i &lt; width; i++)
            sbuf.append(pad);
        return sbuf.toString();
    }

  public static void main (String[] args){
    int x =1;
    double  y =22.123456789;
    double z = 4.5678E-20;

    FormattedWriter out = new FormattedWriter(System.out);
    out.setWidth(10);
    out.setDigits(2);

    out.printf("col1");
    out.printf("col2");
    out.printf("col3");
    out.println();

    out.printf(x);
    out.printf(y);
    out.printf(z);
    out.println();


  }


}


Last Updated: September 2, 2002 4:34 PM