リファレンストップへ Java | メッセージフォーマット使用した環境 JDK 6 Update 11 文字列の特定位置などを置き換えるフォーマットを行います。java.text.MessageFormatを使用します。テンプレート文字列の特定の位置に、動的な文字列をセットしたい場合に使用します。 import java.text.MessageFormat; public class Main { public static void main(String[] args) throws Exception { MessageFormat format = new MessageFormat("{0}をカートに追加しました。現在、カートの中には{1}個の商品が入っています。"); String[] messageArgs = new String[]{"電動ハブラシ", "3"}; String result = format.format(messageArgs); System.out.println(result); } } 結果は以下のようになります。 電動ハブラシをカートに追加しました。現在、カートの中には3個の商品が入っています。 java.text.MessageFormatのコンストラクタにテンプレート文字列を指定します。 {0}や{1}といった文字列は、置き換え用の目印文字列となります。この番号はサンプル中では[messageArgs]の配列のインデックスに該当します。 また、フォーマット文字列の通りの形式の文字列である場合、その文字列の中から、{0}や{1}に該当する文字列を取得(パーズ)する事も可能です。 import java.text.MessageFormat; public class Main { public static void main(String[] args) throws Exception { String str = "電動ハブラシをカートに追加しました。現在、カートの中には3個の商品が入っています。"; MessageFormat format = new MessageFormat("{0}をカートに追加しました。現在、カートの中には{1}個の商品が入っています。"); Object[] messageArgs = format.parse(str); for (Object messageArg : messageArgs) { System.out.println(messageArg); } } } 結果は以下のようになります。 電動ハブラシ 3 本格的な構文解析は正規表現などを使用して行う事になりますが、例えばログの中から特定の文字のみを抜き取るなどの ちょっとした解析であれば、MessageFormat#parseを使用すると、substringやindexofを使用せずに、非常に簡単なソースで目的を達成する事が出来ます。 試しに、Apacheのアクセスログからhtmlページごとのアクセス数を集計する簡単なプログラムを作ってみます。 以下はApache2.2のデフォルト設定のaccess.logの内容の抜粋になります。 127.0.0.1 - - [15/Jul/2009:22:48:11 +0900] "GET /ref/java/core/format/message.html HTTP/1.1" 200 5642 127.0.0.1 - - [15/Jul/2009:22:48:11 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:48:11 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:48:11 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:48:53 +0900] "GET /ref/java/core/format/message.html HTTP/1.1" 200 5645 127.0.0.1 - - [15/Jul/2009:22:48:53 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:48:53 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:48:53 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:49:54 +0900] "GET /ref/java/core/format/num.html HTTP/1.1" 200 5178 127.0.0.1 - - [15/Jul/2009:22:49:54 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:49:54 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:49:54 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:49:55 +0900] "GET /ref/java/core/format/num.html HTTP/1.1" 200 5178 127.0.0.1 - - [15/Jul/2009:22:49:55 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:49:55 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:49:55 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:49:56 +0900] "GET /ref/java/core/format/num.html HTTP/1.1" 200 5178 127.0.0.1 - - [15/Jul/2009:22:49:56 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:49:56 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:49:56 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:49:58 +0900] "GET /ref/java/core/format/date.html HTTP/1.1" 200 7525 127.0.0.1 - - [15/Jul/2009:22:49:58 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:49:58 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:49:58 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:50:01 +0900] "GET /ref/java/core/format/num.html HTTP/1.1" 200 5178 127.0.0.1 - - [15/Jul/2009:22:50:01 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:50:01 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:50:01 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:50:03 +0900] "GET /ref/java/core/format/message.html HTTP/1.1" 200 5645 127.0.0.1 - - [15/Jul/2009:22:50:03 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:50:03 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:50:03 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /ref/java/core/format/message.html HTTP/1.1" 200 5645 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /ref/java/core/format/message.html HTTP/1.1" 200 5645 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:50:04 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 127.0.0.1 - - [15/Jul/2009:22:50:06 +0900] "GET /ref/java/core/format/num.html HTTP/1.1" 200 5178 127.0.0.1 - - [15/Jul/2009:22:50:06 +0900] "GET /style.css HTTP/1.1" 200 2820 127.0.0.1 - - [15/Jul/2009:22:50:06 +0900] "GET /images/categoryLine.png HTTP/1.1" 200 228 127.0.0.1 - - [15/Jul/2009:22:50:06 +0900] "GET /images/logo.png HTTP/1.1" 200 19919 これに対し、以下のような解析プログラムを作成します。 htmlファイルへのアクセスを集計したいので、画像ファイルやcssファイルへのアクセスは集計から除外しています。 import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) throws Exception { // アクセスログのフォーマット MessageFormat format = new MessageFormat("{0} - [{1}] ¥"GET {2} {3}"); // ページ別のアクセス数を保持するマップ Map<URL, アクセス数> Map<String, Integer> accessCount = new HashMap<String, Integer>(); BufferedReader in = null; try { // access.logの読み込み in = new BufferedReader(new InputStreamReader(new FileInputStream("【access.logのパス】"))); String line = null; while ((line = in.readLine()) != null) { Object[] arr = format.parse(line); String url = (String) arr[2]; // URLの末尾(ファイル拡張子)が.htmlでない場合は対象外とする。(画像ファイルやcssは対象外) if (!url.endsWith(".html")) continue; // URLに対するアクセス数を取得し、加算 Integer count = accessCount.get(url); if (count == null) count = 0; accessCount.put(url, count + 1); } } finally { try { in.close(); } catch (Exception e) {} } // 表示 for (String url : accessCount.keySet()) { System.out.println(url + " → " + accessCount.get(url) + "アクセス"); } } } 結果は以下のようになります。 /ref/java/core/format/num.html → 5アクセス /ref/java/core/format/date.html → 1アクセス /ref/java/core/format/message.html → 5アクセス 上記は、簡単な事しかできないプログラムではありますが、substringやindexofで、複雑な事をせずに構文解析が行えている事が分かると思います。 正規表現を使用しても、少ないステップ数でプログラムの作成は可能ですが、java.text.MessageFormatのフォーマット文字列の方が、ぱっと見が分かりやすいので、簡単なログ解析などの場合はMessageFormatを使用すると手軽に解析が行えます。 |
|