■ はじめに
日本の祝日を判定する処理を考えていて、 調べてみると、結構大変そうだなっと。 (例えば、「山の日」は、2020年08月10日で、2021年08月10日。 情勢などでも変わって、単純にプログラムで実装できない部分がある) 更に、過去や未来のメンテナンスまで考えると、更に複雑になる。 ⇒ 理想は、Webサービスで管理して、常に取得とか? で、調査している最中に、内閣府のサイト(※)で、 「昭和30年(1955年)から令和3年(2021年)国民の祝日(csv形式:19KB)」 があった。 まずは、手始めとして、Kotlinでこのファイルを開く方法を考える。
※ 内閣府のサイト
https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
syukujitsu.csv(SJIS)
国民の祝日・休日月日,国民の祝日・休日名称 1955/1/1,元日 1955/1/15,成人の日 ・・・ 2021/10/11,スポーツの日 2021/11/3,文化の日 2021/11/23,勤労感謝の日
目次
■ CSV ■ try-with-resources ■ サンプル
■ CSV
今回は、「syukujitsu.csv」を見る限り、 トリッキーな形式はなさそうだったので String クラスの split メソッドを使用する
https://maku77.github.io/kotlin/numstr/split.html
補足:CSVライブラリ
複雑なCSVであれば... 以下のサイトのように 「Apache commons-csv」や「OpenCSV」などの CSVライブラリを使う方がいい
https://qiita.com/motch0214/items/aecda8e636b857510a90
http://wild-data-chase.com/index.php/2019/06/15/post-860/
■ try-with-resources
https://qiita.com/jutaroi01/items/ee88a402028ef9e338ed
より抜粋、『kotlinにはtry-with-resourcesそのものはない』 代わりに use が使えるらしい。
■ サンプル
準備
* assertsフォルダがない場合は、[New]-[Folder]-[asserts folder] を選択
https://codechacha.com/ja/how-to-use-assets-in-android/
CsvReader.kt
import android.content.res.AssetManager import java.io.BufferedReader import java.io.IOException import java.io.InputStream import java.io.InputStreamReader import java.nio.charset.Charset class CsvReader(assertManager: AssetManager, csvFilePath: String) { private val assertManager = assertManager private val csvFilePath = csvFilePath fun readCsv( skipLine: Int = 0, encoding: String = "UTF-8", delimiter: String = "," ): List<List<String>> { return this.readCsv( this.assertManager.open(this.csvFilePath), skipLine, encoding, delimiter ) } private fun readCsv( inputCsv: InputStream, skipLine: Int, encoding: String, delimiter: String ): List<List<String>> { val csvContents = mutableListOf<List<String>>() try { BufferedReader( InputStreamReader( inputCsv, Charset.forName(encoding) ) ).use { fileReader -> var lineNumber: Int = 1 fileReader.forEachLine { line -> if (line.isNotBlank()) { if (lineNumber > skipLine) { val contents = line.split(delimiter).map { value -> value.trim() } csvContents.add(contents) } } lineNumber++; } } } catch (ex: IOException) { ex.printStackTrace() } return csvContents } }
Main.kt
import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import xxxx.xxx.xxxxx.CsvReader import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button.setOnClickListener { val csvReader = CsvReader(this.assets, "systems/syukujitsu.csv") // 1行目はヘッダーなので飛ばす。SJIS形式を指定。 val csvContents = csvReader.readCsv(1, "SJIS") for (contents in csvContents) { for (content in contents) { Log.i("[Result]", "content = $content") } } } } }
出力結果
I/[Result]: content = 1955/1/1 content = 元日 content = 1955/1/15 content = 成人の日 content = 1955/3/21 ・・・ content = 2021/11/3 content = 文化の日 content = 2021/11/23 content = 勤労感謝の日
参考文献
https://www.programming-shimomura.com/2017/06/23/%E3%80%90android%E3%80%91csv%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF%E3%81%AE%E5%AE%9F%E8%A3%85%EF%BC%88%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E4%BB%98%E3%81%8D%EF%BC%89/
エンコード
https://qiita.com/ryuumikoto/items/2c884b3dfbb228ac1065
https://qiita.com/KenjiOtsuka/items/5a9a3bba715b151bc061
関連記事
Kotlin ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2018/09/13/001546
Kotlin ~ 基本編 / 配列・コレクション ~
https://dk521123.hatenablog.com/entry/2020/07/07/000000
Kotlin ~ 基本編 / クラス ~
https://dk521123.hatenablog.com/entry/2020/07/23/000000
Kotlin ~ 基本編 / 日付・時間 ~
https://dk521123.hatenablog.com/entry/2020/07/27/000000