なんだこれは

はてなダイアリーから移転しました。

scala で gzip解凍とXML操作

scala3 で

scala3 やってみた

JDK のバージョン

まず、scala3 を動かすには Java 11 以上とされているので、インストールしているJDK を調べる

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (5):
    21.0.8 (x86_64) "Eclipse Adoptium" - "OpenJDK 21.0.8" /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home
    21.0.1 (x86_64) "Oracle Corporation" - "Oracle GraalVM 21.0.1+12.1" /Library/Java/JavaVirtualMachines/graalvm-jdk-21.0.1+12.1/Contents/Home
    17.0.16 (x86_64) "Eclipse Adoptium" - "OpenJDK 17.0.16" /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
    11.0.28 (x86_64) "Eclipse Adoptium" - "OpenJDK 11.0.28" /Library/Java/JavaVirtualMachines/temurin-11.jdk/Contents/Home
    1.8.0_392 (x86_64) "Eclipse Temurin" - "Eclipse Temurin 8" /Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home

Java 17 でよさそうなのでこれに変更

$ export JAVA_HOME=$(/usr/libexec/java_home -v 17)

java のバージョンを再確認

$ java -version
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
openjdk version "17.0.16" 2025-07-15
OpenJDK Runtime Environment Temurin-17.0.16+8 (build 17.0.16+8)
OpenJDK 64-Bit Server VM Temurin-17.0.16+8 (build 17.0.16+8, mixed mode)

scala-cli と sbt

scala を動かす方法として簡単なのが scala-cli で プロジェクトをきっちり管理するのが sbt らしい。一旦更新しておいた

cs update

ソースコード

scala3で書くとこうなるんだって感じがある。Javaの資産をうまく使えていて便利。 scala3は本当にライブラリがいくらでもある。すごい

//> using scala "3.7.2"
//> using dep "org.scala-lang.modules::scala-xml:2.4.0"

import java.io.{FileInputStream, InputStreamReader, BufferedReader}
import java.util.zip.GZIPInputStream
import scala.xml.XML

@main def main(args: String*): Unit =
  if args.isEmpty then
    println("Usage: scala-cli run Main.scala -- <path-to-xml.gz>")
  else
    // gzip 展開
    val xmlString =
      val fis = FileInputStream(args(0))
      val gis = GZIPInputStream(fis)
      val br  = BufferedReader(InputStreamReader(gis, "UTF-8"))
      val sb  = new StringBuilder()
      var line: String | Null = null
      while { line = br.readLine(); line != null } do sb.append(line).append("\n")
      br.close()
      sb.toString()

    // XML パース
    val xml = XML.loadString(xmlString)

    // <file-name> タグ抽出
    val files = (xml \\ "file-name").map { node =>
      val contentId = (node \@ "contentId")  // 属性
      val value      = node.text.trim         // タグの値
      (value, contentId)
    }

    // 出力
    println("file-name tags found:")
    files.foreach { case (value, contentId) =>
      println(s"$value,$contentId")
    }

実行

scala-cli run Main.scala -- ~/Downloads/NOTICE.xml.gz