formatメソッド - 萌えJava超入門
第十八章 Stringクラス

formatメソッド

指定された書式文字列に引数を差し込んで、新しい文字列を返します。

public static String format(
       String format, Object... args
       )
このメソッドは奥が深い。
ここでは基本を学ぼう。


目次

1.formatメソッド


書式
String str = String.format("書式文字列", 値...);


これは何事?
いろいろ例外を吐いてくるけど、
どこがおかしいか、
割とちゃんと教えてくれるんだよ。
例外
  java.util.UnknownFormatConversionException
  java.util.MissingFormatArgumentException
  java.util.UnknownFormatFlagsException
  java.util.IllegalFormatWidthException
  java.util.IllegalFormatPrecisionException
  java.util.FormatFlagsConversionMismatchException
  他
書式指示子に不整合があると、上述の例外をスローします。


C言語の「printf」の影響を強く受けています。
C言語のご経験のある方には、かなりなじみ深いメソッドでしょう。



2.サンプルコード


サンプルコードを見ながらでないと
良く分からないと思う。
  1. このメソッドは、クラスメソッド(static) です。
  2. 第一引数に「書式文字列」を取ります。
  3. 書式文字列には、引数リストを差し込むための「書式指示子」を含めます。
  4. 第二引数以降に、書式指示子に与える引数リストを取ります。
  5. 引数リストは、「,」カンマで区切って複数与えることができます。
  6. 引数リストは、書式指示子に則った文字列に編集されます。

String.formatの説明
string_format

//Sample_format_01.java
class Sample_format_01{
    public static void main(String[] args){
      String str1 = String.format("こんにちは、%sさん。", "てまり");
      System.out.println(str1);
    }
}

コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample_format_01.java
ws>java Sample_format_01
こんにちは、てまりさん。


書式文字列 "こんにちは、%sさん。"
書式指示子 %s
引数リスト "てまり"

   結果 こんにちは、てまりさん。

重要
  1. 書式文字列は、生成したい文字列全体です。
  2. 書式指示子は、引数リストを配置する場所と書式を指定します。
  3. 書式文字列の中に「%」があると、書式指示子と認識します。

まずは第一関門。
言葉の意味を理解してくれ。



%s」のところに
「"てまり"」を代入した
ってことでいいのよね。
Wardの差し込み印刷っぽく
ないっすか?



あっ。
そんな感じの
パワーアップ版かも。


3.複数の書式指示子と引数リスト


書式指示子に与える引数リストは、 「,」カンマで区切って複数与えることができます。

引数リストは、前から順番に参照されます。
書式指示子の数と、引数リストの数が一致している必要があります。

//Sample_format_06.java
class Sample_format_06{
    public static void main(String[] args){
      String str1 = String.format(
                  "おはよう、%s君、%s君、%s君!",
                  "静乃", "真夜", "てまり"
                  );
      System.out.println(str1);
    }
}


コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample_format_06.java
ws>java Sample_format_06
おはよう、静乃君、真夜君、てまり君!


値を順番に参照
string_format

順番に参照するんスね。



なのです。


4.書式指示子の書式


書式指示子の書式を説明します。
formatメソッドで面倒なのは
書式指示子だけだ。




また変な記号だし。

書式指示子の書式
%[argument_index$][flags][width][.precision]conversion

「%s」の説明
最初の「%」は書式指示子であることを示す記号です。
「s」は、文字列を表す conversion です。
他の部分は省略されています。
つまり %s は、引数リストの最初の値を、文字列として、何の編集もせずに表示する
という意味でした。

書式指示子は、
全体的にこんな形になる。
書式指示子
書式指示子

flagsは一文字です。
数値ではなく記号です。 「0」以外のフラグもありますが、
「0」以外の数字のフラグはありません。
widthは文字数を表す数値です。
もちろん0で始まることはありません。
複数桁になっても構いません。

flagswidth
境界を絶妙なバランスで
保っている。


5.conversion


%[argument_index$][flags][width][.precision]conversion

conversionは、引数を、何のデータ型として扱い、どのように表示するのかを示す記号です。
書式の最後に、通常一文字(日付/時刻の場合は複数桁の場合あり。)で記載します。

conversion の種類
conversion表示引数のカテゴリ主な引数の型
bString.valueOf(arg)
の値
真偽値
クラス型変数
boolean、Boolean
その他のクラス型
sarg.toString()
の値
文字列
クラス型変数
String
その他のクラス型
cUnicode 文字文字char、Character
byte、Byte
short Short
int、Integer
d10 進整数整数byte、Byte
short、Short
int、Integer
long、Long
BigInteger など
o 8 進整数整数
x16 進整数整数
f10 進数浮動小数点float、Float
double Double
BigDecimal
%%の表示パーセントなし
n改行文字行区切り文字なし
tY日付/時刻long、Long
Calendar、Date
tm日付/時刻
td日付/時刻
tH日付/時刻
tM日付/時刻
tS日付/時刻
tLミリ秒日付/時刻

こんなにあんの?!



あっいや、
とりあえず
sd だけでいいよ。

ご参考までにいろいろな conversion を試してみましょう。
//Sample_format_04.java
class Sample_format_04{
    public static void main(String[] args){
      String str1;

      boolean boo = false;
      str1 = String.format("b = [%b]", boo);
      System.out.println(str1);

      str1 = String.format("s = [%s]", "Hello!");
      System.out.println(str1);

      str1 = String.format("c = [%c]", 'A');
      System.out.println(str1);

      str1 = String.format("d = [%d]", 123);
      System.out.println(str1);

      str1 = String.format("o = [%o]", 123);
      System.out.println(str1);

      str1 = String.format("x = [%x]", 123);
      System.out.println(str1);

      str1 = String.format("f = [%f]", 123.65);
      System.out.println(str1);

      str1 = String.format("パーセント = [%%]");
      System.out.println(str1);

      str1 = String.format("改行 = ABCD[%n]EFG");
      System.out.println(str1);
    }
}

コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample_format_04.java
ws>java Sample_format_04
b = [false]
s = [Hello!]
c = [A]
d = [123]
o = [173]
x = [7b]
f = [123.650000]
パーセント = [%]
改行 = ABCD[
]EFG




日付/時刻は参考程度にしよう?
日付/時刻 は少し難しいですね。
Dateクラスや、Calendarクラスは、このチュートリアルでは扱っていません。
また次の機会に説明させていただきます。

尚、「1$」が付いていますが、これは引数リストが1個しかないので、
argument_indexを指定しています。
1番目の引数を参照して」という意味です。

//Sample_format_05.java
import java.util.Date;

class Sample_format_05{
    public static void main(String[] args){
      String str1;

      Date date = new Date();
      str1 = String.format(
          "t = [%1$tY/%1$tm/%1$td %1$tH:%1$tM %1$tS %1$tL]",
          date
          );
      System.out.println(str1);

    }
}

コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample_format_05.java
ws>java Sample_format_05
t = [1997/08/28 23:55 42 670]



6.argument_index$


%[argument_index$][flags][width][.precision]conversion

argument_index で引数を指定できます。
同じ引数を複数回参照する場合にも利用できます。
Sample_format_05.java (↑)では、1つの引数を何度も参照しています

argument_index の値は 1 から始まり、
  1$ = 引数リストの1番目 (formatメソッドの第二引数)
  2$ = 引数リストの2番目 (formatメソッドの第三引数)
  3$ = 引数リストの3番目 (formatメソッドの第四引数)
と続きます。
//Sample_format_03.java
class Sample_format_03{
    public static void main(String[] args){
      String str1 = String.format(
                  ""おはよう、%2$s君、%1$s君、%3$s君!",
                  "静乃", "真夜", "てまり"
                  );
      System.out.println(str1);
    }
}


コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample_format_03.java
ws>java Sample_format_03
おはよう、真夜君、静乃君、てまり君!


順番が変わった!



後ろに「$」がつくと
argument_index に
なるんだ。


7.空白詰め


%[argument_index$][flags][width][.precision]conversion

width には、最小の文字数を指定します。
引数の桁が width より小さい場合には、半角空白で不足分を補います。
引数の桁が width より大きい場合には、何もしません。

flags を指定しない場合は、右詰めになり、
flags に「-」を与えると、左詰めになります。


//Sample_format_07.java
class Sample_format_07{
    public static void main(String[] args){
      String str1;

      str1 = String.format("[%10d]", 123);    //flagsなし width:10
      System.out.println(str1);

      str1 = String.format("[%10s]", "Hello");//flagsなし width:10
      System.out.println(str1);

      str1 = String.format("[%-10d]", 123);    //flags「-」 width:10
      System.out.println(str1);

      str1 = String.format("[%-10s]", "Hello");//flags「-」 width:10
      System.out.println(str1);
    }
}

これは見た目にも
きれいね。
コマンドライン
>cd ws
ws>javac Sample_format_07.java
ws>java Sample_format_07
[       123] <--- 空白埋め
[     Hello]  <--- 空白埋め
[123       ]  <--- 左寄せ
[Hello     ]  <--- 左寄せ





8.数値の0埋め


引数が数値の場合は、flags に「0」を与えると、0埋めになります。

数値の0埋め
 String str1 = String.format("%05d", 456);

数値の0埋めは定番中の定番だ。
覚えてしまった方がいいかな。
123 を5桁で0埋めして 00123 にしてみましょう。
//Sample_format_02.java
class Sample_format_02{
    public static void main(String[] args){
      String str1 = String.format("%05d", 123);
      System.out.println(str1);
    }
}

コマンドライン
>cd ws
ws>javac Sample_format_02.java
ws>java Sample_format_02
00123

ちなみに、
0以外の文字も行けるんスか?
いや、
残念だが「0」はただのフラグだ。
埋めたい文字を
指定しているわけじゃない。


9.文字列を0埋めする場合


文字列の0埋め
 String str1 = String.format("%10s", "456");
 str1 = str1.replace(' ', '0');

文字列を0埋めしたい場合もあるでしょう。
%05s とすれば、0埋めできそうですが、
0埋めできるのは数値だけです。

//Sample_format_07NG.java
class Sample_format_07NG{
    public static void main(String[] args){
      String str1;
      str1 = String.format("[%05s]", "456");
      System.out.println(str1);
    }
}

コマンドライン
>cd ws
ws>javac Sample_format_07NG.java
ws>java Sample_format_07NG
Exception in thread "main"
java.util.FormatFlagsConversionMismatchException
  : Conversion = s, Flags = 0
  at java.util.Formatter$FormatSpecifier.failMismatch(Unknown Source)
  at java.util.Formatter$FormatSpecifier.checkBadFlags(Unknown Source)
  at java.util.Formatter$FormatSpecifier.checkGeneral(Unknown Source)
  at java.util.Formatter$FormatSpecifier.(Unknown Source)
  at java.util.Formatter.parse(Unknown Source)
  at java.util.Formatter.format(Unknown Source)
  at java.util.Formatter.format(Unknown Source)
  at java.lang.String.format(Unknown Source)
  at Sample_format_07NG.main(Sample_format_07NG.java:5)

「Conversion = s に Flags = 0 はムリだっつーの。」の意



%5s で空白埋めしてから、replaceメソッドを使う方法が一般的です。

//Sample_format_08.java
class Sample_format_08{
    public static void main(String[] args){
      String str1;
      str1 = String.format("[%10s]", "456");//flagsなし width:10
      System.out.println(str1);
      str1 = str1.replace(' ','0');
      System.out.println(str1);
    }
}

コマンドライン
>cd ws
ws>javac Sample_format_08.java
ws>java Sample_format_08
[       456]
[0000000456]


この方法なら
いろいろな文字で
埋められますね。
だろ?
うまく使ってくれ

文字列を0埋め
 String str1 = String.format("[%10s]", "456");
 str1 = str1.replace(' ','0');

           str1 → [0000000456]



お疲れ様でした。


© 2019 awasekagami