Kotlin

ファイルと文字列データ

JVMのファイル操作でUTF-8の読み書きを行い、保存したデータを検証します。

対象:Kotlin 2系・JDK 17以降のJVMコンソールアプリを対象にします。Android専用のAPIは使いません。

01

準備と保存先

このページはJVM専用です。java.io.Fileを使うため、ブラウザーのKotlin Playgroundなどでは実行できない場合があります。空の練習フォルダーにMain.ktを置き、入門と同じ方法でコンパイル・実行します。各例は独立しており、ファイルを作業フォルダーに作成・上書きします。

IDEの作業フォルダーはソースのある場所と異なる場合があります。生成ファイルが見つからないときは file.absolutePath を表示して確認します。Androidアプリではアプリ専用の保存領域と権限を別途学びます。
02

UTF-8で書き込みと読み込み

writeText はテキストを保存し、readText は全体を読みます。文字コードをUTF-8に揃えます。ファイルを開けないなどの失敗はIOExceptionで受け取れます。

Main.kt(全体を置き換え)KOTLIN
import java.io.File
import java.io.IOException

fun main() {
    val file = File("kotlin-memo.txt")
    try {
        file.writeText("Kotlinの学習メモ", Charsets.UTF_8)
        println(file.readText(Charsets.UTF_8))
    } catch (error: IOException) {
        println("保存または読み込みに失敗しました")
    }
}
実行結果OUTPUT
Kotlinの学習メモ
03

追記して行ごとに処理

appendText は既存の末尾へ追加します。useLines は行を順に扱い、処理を終えたらファイルを閉じます。改行は \n で表します。この例は最初にwriteTextで初期化するため、何度実行しても3行になります。

Main.kt(全体を置き換え)KOTLIN
import java.io.File
import java.io.IOException

fun main() {
    val file = File("kotlin-minutes.txt")
    try {
        file.writeText("10\n20\n", Charsets.UTF_8)
        file.appendText("30\n", Charsets.UTF_8)
        file.useLines(Charsets.UTF_8) { lines ->
            for (line in lines) println(line)
        }
    } catch (error: IOException) {
        println("ファイルを処理できませんでした")
    }
}
実行結果OUTPUT
10
20
30

useLinesのlinesはブロック内で消費します。閉じた後に使うため、そのまま外へ返してはいけません。大きなファイルでは全体をreadTextで読み込むより、行ごとの処理が適しています。

04

行の内容を検証する

読み込んだ文字列をそのまま信頼せず、数値に変換できるかと範囲を確かめます。次の例は不正な行を知らせて合計から除きます。業務によっては1行でも不正なら全体を失敗にする設計もあります。

Main.kt(全体を置き換え)KOTLIN
import java.io.File
import java.io.IOException

fun main() {
    val file = File("kotlin-data.txt")
    try {
        file.writeText("10\nabc\n-2\n20\n", Charsets.UTF_8)
        var total = 0
        file.useLines(Charsets.UTF_8) { lines ->
            for ((index, line) in lines.withIndex()) {
                val minutes = line.toIntOrNull()
                if (minutes == null || minutes < 0) {
                    println("${index + 1}行目は不正です")
                } else {
                    total += minutes
                }
            }
        }
        println("合計: $total")
    } catch (error: IOException) {
        println("ファイルを処理できませんでした")
    }
}
実行結果OUTPUT
2行目は不正です
3行目は不正です
合計: 30

この形式は「1行に整数1個」という単純な仕様です。CSVは引用符や区切り文字、JSONは構造と型の規則があるため、実際に扱うときは対応するパーサーを使います。

05

練習:空行を除いて数える

空白だけの行を除いた行数を数えます。次の入力なら2です。ファイルの読み込み失敗も処理してください。

解答例と結果を確認する

まず自分で書いてから、処理の順番と結果を比べましょう。

Main.kt(全体を置き換え)KOTLIN
import java.io.File
import java.io.IOException

fun main() {
    val file = File("kotlin-notes.txt")
    try {
        file.writeText("変数\n\n関数\n  \n", Charsets.UTF_8)
        val count = file.useLines(Charsets.UTF_8) { lines ->
            lines.count { line -> line.isNotBlank() }
        }
        println(count)
    } catch (error: IOException) {
        println("ファイルを処理できませんでした")
    }
}
実行結果OUTPUT
2

公式ドキュメントで確認する:kotlin.io API