5. フォーマット入出力
2005.10.11 株式会社四次元データ 宮澤了祐
- 5.1. 書式指定子の記述方法1
J2SE5.0より追加された機能に、書式を付加した入出力機能があります。 C言語でのprintfやscanfのように、形式を指定して入出力を行うものです。 例えばある変数の値を出力するプログラムは、以下のようになります。
int a = 123; System.out.printf("変数aの値は%dです。",a);
printf()メソッドが、標準出力に書式を指定して出力するメソッドです。 第一引数で書式情報の含まれる文字列、第二引数以下で変換される値を指定します。 このプログラムは次のように出力されます。
変数aの値は123です。
この「%d」の部分が「書式指定子」です。dの部分を「変換文字」といい、いくつか種類があります。 これらの書式付き出力を実現するメソッドは「java.util.Formatter」に実装されています。 直接このクラスを使用することも可能ですが、 System.outやSystem.errなどの標準出力ストリームで使用されているPrintStreamクラスにも、 書式付出力を可能にするメソッドが追加されました。 PrintStream.printf()及びPrintStream.format()メソッドがそれです。 この二つは名前が違うだけで同じメソッドです。
また出力されるものを文字列として生成するメソッド、format()がjava.lang.Stringに追加されました。 これは書式情報に基づき、変換を加えた文字列を出力する、staticなメソッドとして実装されています。
以下は全て同じ内容を出力します。
import java.util.Formatter; public class FormatIOSample { public static void main(String[] args) { int a = 123; int b = 456; //PrintStreamを使用 System.out.printf("変数a:%d 変数b:%d\n",a,b); System.out.format("変数a:%d 変数b:%d\n",a,b); //String.format()メソッドを使用 String str = String.format("変数a:%d 変数b:%d\n",a,b); System.out.print(str); //java.util.Formatterクラスを使用。 Formatter format = new Formatter(); format.format("変数a:%d 変数b:%d\n",a,b); System.out.print(format.out()); } }
5.1. 書式指定子の記述方法1
書式指定子は以下のような形式で記述します。([]内は省略可能です。)
%[引数インデックス][フラグ][幅][.精度]変換文字
変換文字には次のものがあります。 大文字と小文字がある場合、大文字の変換文字を使えば変換後の値が大文字になります。
変換文字 | 説明 | 引数の型 |
---|---|---|
b,B | "true"または"false"に変換されます。nullは"false"に変換されます。 | 任意の型 |
h,H | 16進数のハッシュ値です。nullならば"null"と出力されます。 | 任意の型 |
s,S | 文字列に変換します。nullなら"null"と出力されます。 Formattableインタフェースを実装している場合はformatTo()メソッドの戻り値、 それ以外ならtoStringメソッドの戻り値です。 | 任意の型 |
c | 文字列 | java.lang.Character、java.lang.Byte、java.lang.Short、java.lang.Integer |
d | 十進数 | java.lang.Byte、java.lang.Short、java.lang.Integer、java.lang.Long、java.math.BigInteger |
o | 八進数 | |
x,X | 16進数 | |
e,E | 指数表示 | java.lang.Float、java.lang.Double、java.math.BigDecimal |
f | 小数 | |
g,G | 四捨五入処理後の精度および値の大きさにより、小数または指数表示 | |
a,A | 16進数の指数表示 | |
t,T | 日付と時間です。詳細は下記参照。 | java.lang.Long、java.util.Calender,java.util.Date |
n | 改行します。 | なし |
ここで注意が必要なのが引数の型です。 任意の型が指定出来るs,bなどでは問題が発生しませんが、 指定出来ない型を指定してしまった場合、コンパイルの段階ではエラーが発生しません。 実行時にjava.lang.IllegalFormatConversionExceptionが発生しプログラムが停止します。
引数インデックス
C言語のprintfとの相違点の一つに、引数にインデックスをつけられる点があります。 書式指定子に対応する引数を指定出来る明示インデキシングと、相対インデキシングがあります。 以下は明示インデキシングのサンプルです。
int a1 = 1, a2 = 2, a3 = 3; System.out.printf("a2は%2$d、a3は%3$d、a1は%1$dです。", a1, a2, a3);
次のように出力されます。
a2は2、a3は3、a1は1です。
書式指定を開始する添字%の直後に、何番目の引数かを示す数値と「$」を挿入することで、置換引数を明示的に示します。 1番目の引数を置換する場合は「%1$変換文字」といった形です。
相対インデキシングは、一つ前の書式指定子と同じ引数を使用する場合に利用できます。 相対インデキシングを用いたい場合は、「%」の直後に「<」を挿入します。
int a = 100; System.out.printf("%dは16進数で%<x、8進数で%<oです。",a);このように出力されます。
100は16進数で64、8進数で144です。
インデックスを指定した書式指定子と、通常の書式指定子が混在している場合、 通常の書式指定子は、インデックスを指定した書式指定子と無関係に動作します。
int a1 = 1, a2 = 2, a3 = 3; System.out.printf("a2は%2$d、a3は%d、a1は%dです。",a1,a2,a3);
最初のみインデックスを指定しています。これは次のように出力されます。
a2は2、a3は1、a1は2です。
二番目以降の書式指定子は、先頭の書式指定子と無関係に動作しています。 それぞれ別個に処理されるものと考えてください。