Java 文字列操作
[履歴] [最終更新] (2017/07/19 23:48:33)
最近の投稿
注目の記事

正規表現

import java.util.regex.Pattern;
import java.util.regex.Matcher;

class Main {
    public static void main(String args[]) {

        {
            // 完全一致
            Pattern pattern = Pattern.compile("^http://www\\.");
            Pattern pattern2 = Pattern.compile("abc", Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher("http://www.example.com");
            Matcher matcher2 = pattern2.matcher("ABC");
            System.out.println(matcher.matches()); //=> false (注意: 部分一致は find)
            System.out.println(matcher2.matches()); //=> true
        }
        {
            // 部分一致
            Pattern pattern = Pattern.compile("^http://www\\.");
            Pattern pattern2 = Pattern.compile("abc", Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher("http://www.example.com");
            Matcher matcher2 = pattern2.matcher("ABC");
            System.out.println(matcher.find()); //=> true
            System.out.println(matcher2.find()); //=> true
        }
        {
            // 部分一致を複数回実施すると false になります。
            Pattern pattern2 = Pattern.compile("abc", Pattern.CASE_INSENSITIVE);
            Matcher matcher2 = pattern2.matcher("abc|abcd");
            while(matcher2.find()) {
                System.out.println(matcher2.group()); //=> abc => abc
            }
        }

        // 後方参照を用いた置換
        Pattern pattern3 = Pattern.compile("(a)b(c)");
        Matcher matcher3 = pattern3.matcher("abc|abcd");
        System.out.println(matcher3.replaceAll("$1_$2")); //=> a_c|a_cd
        System.out.println("abc|abcd".replaceAll("(a)b(c)", "$1_$2")); //=> a_c|a_cd (String クラスだけで実現; 後述の replace と区別)

        // 後方参照
        Pattern pattern4 = Pattern.compile("^(\\d{4})/(\\d{2})/(\\d{2})$");
        Matcher matcher4 = pattern4.matcher("9999/12/31");
        if(matcher4.find()) {
            System.out.println(matcher4.group(0)); //=> 9999/12/31
            System.out.println(matcher4.group(1)); //=> 9999
            System.out.println(matcher4.group(2)); //=> 12
            System.out.println(matcher4.group(3)); //=> 31
        }

        // ^ と $ の意味
        Pattern pattern5a = Pattern.compile("^xyz$");
        Pattern pattern5b = Pattern.compile("^xyz$", Pattern.MULTILINE);
        String str5 = "xyz\nxyz";
        System.out.println(pattern5a.matcher(str5).find()); //=> false (文字列全体の最初 ^ と最後 $)
        System.out.println(pattern5b.matcher(str5).find()); //=> true (各行の最初 ^ と最後 $)
    }
}

文字コードの変換

import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.io.PrintWriter;

class Main {
    public static void main(String args[]) {

        // ファイルのエンコーディングは UTF-8 であるとします。
        // その場合、JVM は UTF-8 で起動する必要があります。
        // (環境によっては明示的に指定する必要があります
        //  java -Dfile.encoding=UTF-8 Main)
        String str = "ゆーてぃーえふえいと";
        System.out.println(System.getProperty("file.encoding")); //=> UTF-8

        // str には「文字列」が格納されています。デコードされており、既に UTF-8 ではありません。

        try {
            // 「文字列」をエンコードしてファイルに書き込む
            // (file.encoding の既定値でない場合、エンコーディング方法の指定が必要)
            PrintWriter pw = new PrintWriter("res.txt");
            // PrintWriter pw = new PrintWriter("res.txt", "Shift_JIS");
            // PrintWriter pw = new PrintWriter("res.txt", "EUC-JP");
            pw.write(str);
            pw.close();
        }
        catch(FileNotFoundException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        try {
            // 「文字列」を各種文字コードにエンコーディング
            // (file.encoding の既定値でない場合、エンコーディング方法の指定が必要)
            byte[] utf8 = str.getBytes();
            byte[] sjis = str.getBytes("Shift_JIS");
            byte[] euc = str.getBytes("EUC-JP");

            System.out.println(utf8); //=> [B@1540e19d
            System.out.println(sjis); //=> [B@677327b6
            System.out.println(euc); //=> [B@14ae5a5

            // エンコードされたバイト列を再び「文字列」にデコーディング
            // (file.encoding の既定値でない場合、デコーディング方法の指定が必要)
            String str1 = new String(utf8);
            String str2 = new String(sjis, "Shift_JIS");
            String str3 = new String(euc, "EUC-JP");
            System.out.println(str1); //=> ゆーてぃーえふえいと
            System.out.println(str2); //=> ゆーてぃーえふえいと
            System.out.println(str3); //=> ゆーてぃーえふえいと
        }
        catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

Base64 エンコーディング (Java 8)

import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Base64.Decoder;
import java.io.UnsupportedEncodingException;

class Main {
    public static void main(String args[]) {
        try {
            String str = "日本語";
            Encoder encoder = Base64.getEncoder();
            byte[] bytes = encoder.encode(str.getBytes("UTF-8"));

            // Base64 エンコード結果は ASCII コードのバイト列
            // https://www.qoosky.io/techs/69369792d4
            System.out.println(new String(bytes)); //=> 5pel5pys6Kqe

            Decoder decoder = Base64.getDecoder();
            byte[] bytes2 = decoder.decode(bytes);

            System.out.println(new String(bytes2, "UTF-8")); //=> 日本語
        }
        catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

以下の結果と一致

$ echo '日本語' | base64
5pel5pys6Kqe

URL エンコーディング

import java.net.URLEncoder;
import java.net.URLDecoder;
import java.io.UnsupportedEncodingException;

class Main {
    public static void main(String args[]) {
        try {
            String str = "http://www.example.com/search?q=日本語";
            String encoded = URLEncoder.encode(str, "UTF-8");
            System.out.println(encoded); //=> http%3A%2F%2Fwww.example.com%2Fsearch%3Fq%3D%E6%97%A5%E6%9C%AC%E8%AA%9E

            String decoded = URLDecoder.decode(encoded, "UTF-8");
            System.out.println(decoded); //=> http://www.example.com/search?q=日本語
        }
        catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

ハッシュ値

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;

class Main {
    public static void main(String args[]) {
        try {
            // バイト列のハッシュ値を取得
            MessageDigest md5 = MessageDigest.getInstance("MD5"); // SHA-1, SHA-256
            md5.update("ABC".getBytes("UTF-8"));
            byte[] hash = md5.digest();
            System.out.println(hash.length); //=> 16

            // 16 進数文字列として出力
            StringBuilder sb = new StringBuilder();
            for(byte b : hash) {
                String hex = String.format("%02x", b); // 16 進数 2 桁として表示 (1byte は 00 ~ ff)
                sb.append(hex);
            }
            System.out.println(sb); //=> 902fbdd2b1df0c4f70b4a5d23525e932 (32 文字)
        }
        catch(NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

以下の結果と一致

$ echo 'ABC' | md5sum
902fbdd2b1df0c4f70b4a5d23525e932  -

数値と文字列の相互変換

10 進数

class Main {
    public static void main(String args[]) {

        // 不正な文字列のときは NumberFormatException が発生します。
        // (例外について → https://www.qoosky.io/techs/23bd8ad94d
        int i = Integer.parseInt("1");
        long l = Long.parseLong("1");
        double d = Double.parseDouble("1.0");

        System.out.println(i); //=> 1
        System.out.println(l); //=> 1
        System.out.println(d); //=> 1.0

        String iStr = String.valueOf(i); // 文字列に変換
        String dStr = String.valueOf(d);
    }
}

N 進数

class Main {
    public static void main(String args[]) {

        // 文字列 → 数値
        int iBinary = Integer.parseInt("11111111", 2);
        int iHex = Integer.parseInt("ff", 16);
        int iHex2 = Integer.parseInt("FF", 16);

        System.out.println(iBinary); //=> 255
        System.out.println(iHex); //=> 255
        System.out.println(iHex2); //=> 255

        // 数値 → 文字列
        System.out.println(Integer.toBinaryString(iBinary)); //=> 11111111
        System.out.println(Integer.toHexString(iHex)); //=> ff
    }
}

その他の基本的な処理

import java.io.UnsupportedEncodingException;

class Main {
    public static void main(String args[]) {

        // 書式指定
        System.out.println(String.format("%s %d", "文字列", 123)); //=> 文字列 123

        // 長さ
        System.out.println("あいうえお".length()); //=> 5 (Unicode 文字列としての長さ)
        try {
            System.out.println("あいうえお".getBytes("UTF-8").length); //=> 15 (エンコードした結果のバイト数)
            System.out.println("あいうえお".getBytes("Shift_JIS").length); //=> 10 (エンコードした結果のバイト数)
        }
        catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 大文字小文字の変換
        System.out.println("Abc".toUpperCase()); //=> ABC
        System.out.println("Abc".toLowerCase()); //=> abc

        // 開始文字列および終了文字列の確認
        System.out.println("xyz".startsWith("xy")); //=> true
        System.out.println("xyz".endsWith("yz")); //=> true

        // ruby の strip 関数 (前後の半角スペースやタブ、改行を除去)
        System.out.println(" abc \n\t".trim()); //=> abc

        // 部分文字列
        System.out.println("あいうえお".substring(2)); //=> うえお (index: 2..-1)
        System.out.println("あいうえお".substring(2,3)); //=> う (index: 2..(3-1))

        // 分割
        String[] res = "a, bbb,c".split(",");
        System.out.println(res[0]); //=> a
        System.out.println(res[1]); //=> " bbb"

        // 連結
        // '+' 演算子は連結する度にメモリを確保して新しい String オブジェクトを生成します。
        // ループ処理などでは GC が頻発することに注意 (以下の例ではコンパイル時に "abcxyz" に最適化されるため問題なし)
        String str = "abc" + "xyz";

        // ループ処理時はこちらを使用
        StringBuilder sb = new StringBuilder();
        // StringBuffer sb = new StringBuffer(); // マルチスレッドではこちらが安全。StringBuilder と比較すると低速。
        sb.append("abc");
        sb.append("xyz");
        String str2 = sb.toString();

        // java8 のみ
        String str3 = String.join("_", "abc", "def", "xyz");
        java.util.ArrayList<String> list = new java.util.ArrayList<String>();
        list.add("abc");
        list.add("xyz");
        String str4 = String.join("_", list);

        System.out.println(str); //=> abcxyz
        System.out.println(str2); //=> abcxyz
        System.out.println(str3); //=> abc_def_xyz
        System.out.println(str4); //=> abc_xyz

        // 置換
        System.out.println("abbb|bb".replace("bb", "xx")); //=> axxb|xx (前述の replaceAll と異なり正規表現扱いされない)

        // 検索
        System.out.println("a,b,c,".indexOf(",")); // 1 (最初にヒットした箇所のインデックス)
        System.out.println("a,b,c,".indexOf("|")); // -1 (ヒットせず)
        System.out.println("a,b,c,".lastIndexOf(",")); // 5 (後ろから検索)
    }
}

StringUtils の導入

GradleMaven において、The Central Repository で確認できる以下のような設定を行うことで、StringUtils という文字列処理のためのクラスが利用できるようになります。Apache Commons に含まれる Java の機能拡張ライブラリのうち、特に java.lang パッケージを拡張する Commons Lang が提供するクラスです。

compile('org.apache.commons:commons-lang3:3.6')

サンプルコード

JavaDoc に豊富なサンプルコードが存在します。

インポート

import org.apache.commons.lang3.StringUtils;

存在確認

StringUtils.isEmpty(null); // true
StringUtils.isEmpty(""); // true
StringUtils.isEmpty(" "); // false

StringUtils.isBlank(null); // true
StringUtils.isBlank(""); // true
StringUtils.isBlank(" "); // true
関連ページ
    概要 Rails における ERB と同様に、Spring Boot でもテンプレートエンジンを利用できます。今回は特に Thymeleaf (タイムリーフ) のサンプルコードを、こちらのページで構築した環境をもとにまとめます。 公式ドキュメント Serving Web Content with Spring MVC
    概要 Android で利用される HTTP クライアントには Volley や OkHttp がありますが、ここでは Android プラットフォームに標準で導入されている HttpsURLConnection (HttpURLConnection) を利用します。 また、Android では HTTP 通信を main スレッドではなくバックグラウンドの別スレッドで非同期に行う必要があり、