From 912ca51cd6ace312dfd79875999d0cb1415353d5 Mon Sep 17 00:00:00 2001 From: Guntis Smaukstelis Date: Thu, 30 Jan 2025 15:53:26 +0200 Subject: [PATCH] Parse grib file initial attempt --- .gitignore | 1 + README.md | 3 ++ src/main/scala/grib/Grib.scala | 6 +++ src/main/scala/grib/GribParser.scala | 59 ++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 src/main/scala/grib/Grib.scala create mode 100644 src/main/scala/grib/GribParser.scala diff --git a/.gitignore b/.gitignore index 7d22581..bf27d1a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ src/main/resources/application.conf postgres/ target/ +data/ project/target/ project/project/target/ .bsp diff --git a/README.md b/README.md index e809fa6..38d932d 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,9 @@ cd web/ npm run dev ``` +Run one file +```sbt "runMain grib.GribParser"``` + ## Backend Tech: - scala: cats-effects, http4s, fs2, circe, scalatest - postgres diff --git a/src/main/scala/grib/Grib.scala b/src/main/scala/grib/Grib.scala new file mode 100644 index 0000000..2ab327a --- /dev/null +++ b/src/main/scala/grib/Grib.scala @@ -0,0 +1,6 @@ +package grib +case class Grib( + version: Int, + discipline: Int, + length: Long, + ) \ No newline at end of file diff --git a/src/main/scala/grib/GribParser.scala b/src/main/scala/grib/GribParser.scala new file mode 100644 index 0000000..ed43521 --- /dev/null +++ b/src/main/scala/grib/GribParser.scala @@ -0,0 +1,59 @@ +package grib + +import cats.effect._ +import cats.effect.unsafe.implicits.global +import fs2.io.file.{Files, Path} + +import java.nio.ByteBuffer + +// sbt "runMain grib.GribParser" +object GribParser { + def parseFile(path: Path): IO[List[Grib]] = { + def loop(ptr: Long, acc: List[Grib]): IO[List[Grib]] = { + for { + fileSize <- Files[IO].size(path) + result <- if (ptr >= fileSize) { + IO.pure(acc.reverse) + } else { + for { + grib <- parseGrib(path, ptr) + nextResult <- loop(ptr + grib.length, grib :: acc) + } yield nextResult + } + } yield result + } + + loop(0L, List.empty) + } + + def parseGrib(path: Path, ptr: Long): IO[Grib] = { + for { + bytes <- readBytes(path, ptr, 16) + identifier = new String(bytes.take(4), "ASCII") + discipline = bytes(6) + version = bytes(7) + length = ByteBuffer.wrap(bytes.slice(8, 16)).getLong + _ <- IO.println(identifier, version, discipline, length) + grib = Grib(version, discipline, length) + } yield grib + } + + + def readBytes(path: Path, ptr: Long, len: Int): IO[Array[Byte]] = { + Files[IO].readRange(path, 4096, ptr, ptr + len) + .compile + .to(Array) + } + + def main(args: Array[String]): Unit = { + val fileName = "data/HARMONIE_DINI_SF_2025-01-24T030000Z_2025-01-26T010000Z.grib" + val path = Path(fileName) + + // Example of running the effect + val program = for { + _ <- parseFile(path) + } yield () + + program.unsafeRunSync() + } +} \ No newline at end of file