This post if from 2016, hope its helpful (it’s aimed at me when I’ve forgotten how)

Straight to the code again, and please see the previous post for an explanation deeper than I’ve given below - ie zero explanation.

// use an object just to create a terse example which is runnable
object WriteAndReadAFile extends App {
  // Ensures the resource is closed
  def using[A <: {def close() : Unit}, B](closeable: A)(f: A => B): B =
    try f(closeable) finally closeable.close()

  def readData(fileName: String): Try[List[(Int, Long, Int)]] = {
    @tailrec
    def readDataInputStream(acc: ArrayBuffer[(Int, Long, Int)], dis: DataInputStream): Try[List[(Int, Long, Int)]] = {
      if (dis.available() == 0) Success(acc.toList)
      else readDataInputStream(acc += Tuple3(dis.readInt(), dis.readLong, dis.readInt), dis)
    }

    def readIndexFileStream(fis: FileInputStream): Try[List[(Int, Long, Int)]] = {
      for {
        dis <- Try(new DataInputStream(fis))
        listOfTuples <- readDataInputStream(ArrayBuffer.empty[(Int, Long, Int)], dis)
      } yield listOfTuples
    }

    Try(using(new FileInputStream(fileName))(readIndexFileStream)).flatten
  }

  def writeData(fileName:String, data: List[(Int,Long,Int)]) :Try[Unit] = {
    // Curried, so we can partially apply the data argument prior to calling using
    def writeIndexRandomAccessFile(data:List[(Int, Long, Int)])(raf: RandomAccessFile): Try[Unit] = {
      Try {
        raf.seek(0)
        data.foreach{case (seqNo, pos, len)=> {
          raf.writeInt(seqNo)
          raf.writeLong(pos)
          raf.writeInt(len)
        }}}
    }

    Try(using(new RandomAccessFile(fileName, "rw"))(writeIndexRandomAccessFile(data))).flatten
  }
  // inlining the testing
  val fileName = "indexFile.idx"
  writeData(fileName, List[(Int,Long,Int)]((1,0,50),(2,50,10),(3,60,5),(4,65,1))) match {
    case Failure(ex) =>
      println(s"Could not write file $fileName, detail ${ex.getClass.getName}:${ex.getMessage}")
    case _ =>
  }
  readData(fileName) match {
    case Success(data) => println(s"Data read: ${data.mkString(",")}")
    case Failure(ex) =>
      println(s"Could not read file $fileName, detail ${ex.getClass.getName}:${ex.getMessage}")
  }
}

No explanation! This is a follow on from the previous post, so look there for notes.