Kotlinでは、文字列の切り出し(部分抽出・分割・加工)を行うためのAPIが非常に豊富に用意されています。
しかし、substring のような低レベルAPIを安易に使うと、例外発生・境界バグ・想定外の文字欠損といった問題につながることも少なくありません。
本記事では、
- Kotlinの文字列の基本
- 安全かつ可読性の高い切り出し方法
- 実務で頻出するパターン
- よくある落とし穴とその回避策
を体系的に解説します。
目次
KotlinのStringの基本
Kotlinの String は以下の特徴を持ちます。
- イミュータブル(不変)
- 内部表現は UTF-16
CharSequenceを実装- Javaの
Stringと完全互換(JVM)
val text = "Hello Kotlin"
文字列の切り出し操作は、必ず新しい String を生成します。
元の文字列が変更されることはありません。
substring() ― 最も基本的な切り出し
インデックス指定
val text = "Hello Kotlin"
val result = text.substring(0, 5)
println(result) // Hello
- 開始インデックスは 含む
- 終了インデックスは 含まない
開始位置のみ指定
val result = text.substring(6)
println(result) // Kotlin
注意点
substring は 範囲外アクセスに対して例外を投げます。
text.substring(0, 100) // StringIndexOutOfBoundsException
入力値が保証されていないケースでは、実務利用は慎重に行う必要があります。
Range(IntRange)を使った切り出し
Kotlinでは IntRange を使った substring も利用できます。
val text = "Hello Kotlin"
val result = text.substring(0..4)
println(result) // Hello
特徴
- 両端を含む(
0..4) - 可読性が高い
- Kotlin標準ライブラリの拡張関数(一般的なKotlin/JVM環境で利用可能)
until を使った表現(推奨)
val result = text.substring(0 until 5)
substring(start, end) と意味が一致し、境界の混乱を防げます。
take / drop ― 安全性重視の切り出し
先頭から取得(take)
val text = "Hello Kotlin"
val result = text.take(5)
println(result) // Hello
先頭から削除(drop)
val result = text.drop(6)
println(result) // Kotlin
メリット
- 範囲外指定でも 例外が発生しない
- 実務コードで非常に安全
"Hi".take(10) // "Hi"
"Hi".drop(10) // ""
※ UTF-16単位で処理されるため、絵文字などでは「見た目上の1文字」が分断される可能性があります。
takeLast / dropLast ― 末尾操作
val text = "Hello Kotlin"
text.takeLast(6) // Kotlin
text.dropLast(7) // Hello
- ファイル名
- ログの末尾情報
- 拡張子処理
などで頻出します。
split() ― 区切り文字で分割
単純な分割
val csv = "apple,banana,orange"
val list = csv.split(",")
結果
["apple", "banana", "orange"]
複数区切り文字
val text = "2026-01/11"
val list = text.split("-", "/")
limit指定(重要)
val text = "key=value=extra"
val result = text.split("=", limit = 2)
結果
["key", "value=extra"]
設定ファイル・ログ解析では limit の指定が非常に重要です。
正規表現(Regex)を使った抽出
matchして値を取り出す
val text = "ID:12345"
val regex = Regex("""ID:(\d+)""")
val id = regex.find(text)?.groupValues?.get(1)
空白などをまとめて分割
val text = "apple banana\torange"
val list = text.split(Regex("\\s+"))
連続区切りがある場合に有効です。
substringBefore / substringAfter ― 実務で最も安全なAPI
区切りの前後を取得
val email = "user@example.com"
email.substringBefore("@") // user
email.substringAfter("@") // example.com
デリミタが見つからない場合の挙動
"text".substringAfter("@") // ""
"text".substringAfter("@", "default") // default
"text".substringBefore("@") // "text"
After系:空文字 or 指定デフォルトBefore系:元の文字列が返る(デフォルト)
Last系(URL・パス操作)
val path = "/usr/local/bin"
path.substringAfterLast("/") // bin
path.substringBeforeLast("/") // /usr/local
インデックス検索+切り出し(注意が必要)
val text = "Hello Kotlin"
val index = text.indexOf("Kotlin")
if (index >= 0) {
val result = text.substring(index)
}
この方法は柔軟ですが、境界チェックを必ず行う必要があります。
拡張子取得の安全な例
val file = "sample.txt"
val ext = file.substringAfterLast(".", missingDelimiterValue = "")
拡張子が存在しない場合でも安全です。
1文字ずつ扱う場合
val text = "Kotlin"
text[0] // 'K'
条件付き抽出
val upper = text.filter { it.isUpperCase() }
日本語・絵文字の注意点
val text = "こんにちは"
text.length // 5
絵文字の場合
val emoji = "😀"
emoji.length // 2(UTF-16のサロゲートペア)
- 絵文字は 2以上の長さになることがある
- 見た目の1文字 ≠ length 1
- JVMでは
codePoints()を使うことでコードポイント単位処理が可能(Kotlin/JVM限定)
実務での使い分け指針
| 目的 | 推奨API |
|---|---|
| 範囲が保証されている | substring |
| 安全性重視 | take / drop |
| 区切り文字処理 | substringBefore / After |
| 設定・ログ解析 | split(limit) |
| 複雑な条件 | Regex |
まとめ
Kotlinの文字列切り出しは、
- 低レベルだが強力な
substring - 安全で読みやすい
take / drop - 実務最適解になりやすい
substringBefore / After - 柔軟な
Regex
を適切に使い分けることが重要です。
「とりあえず substring」ではなく、入力の信頼性・可読性・保守性を意識してAPIを選ぶことで、堅牢なKotlinコードが書けるようになります。
以上、Kotlinの文字列の切り出しについてでした。
最後までお読みいただき、ありがとうございました。










