В Scala, как читать байты из двоичного файла, разделенного символами? - PullRequest
0 голосов
/ 15 ноября 2018

В Scala, учитывая двоичный файл, я заинтересован в получении списка элементов Array [Byte].

Например, двоичный файл содержит элементы, разделенные символами / байтами 'my-delimiter'.

Как получить список массивов [байт] для каждого элемента?

1 Ответ

0 голосов
/ 15 ноября 2018

Функциональное решение, с помощью java.nio:

import java.nio.file.{Files, Paths}

object Main {

  private val delimiter = '\n'.toByte

  def main(args: Array[String]): Unit = {
    val byteArray = Files.readAllBytes(Paths.get(args(0)))

    case class Accumulator(result: List[List[Byte]], current: List[Byte])

    val items: List[Array[Byte]] = byteArray.foldLeft(Accumulator(Nil, Nil)) {
      case (Accumulator(result, current), nextByte) =>
        if (nextByte == delimiter)
          Accumulator(current :: result, Nil)
        else
          Accumulator(result, nextByte :: current)
    } match {
      case Accumulator(result, current) => (current :: result).reverse.map(_.reverse.toArray)
    }
    items.foreach(item => println(new String(item)))
  }

}

Ожидается, что это решение будет иметь низкую производительность.Насколько это важно для вас?Сколько файлов, какого размера и как часто вы будете читать?Если важна производительность, лучше использовать входные потоки и изменяемые коллекции:

import java.io.{BufferedInputStream, FileInputStream}

import scala.collection.mutable.ArrayBuffer

object Main {

  private val delimiter = '\n'.toByte

  def main(args: Array[String]): Unit = {
    val items = ArrayBuffer.empty[Array[Byte]]
    val item = ArrayBuffer.empty[Byte]
    val bis = new BufferedInputStream(new FileInputStream(args(0)))
    var nextByte: Int = -1
    while ( { nextByte = bis.read(); nextByte } != -1) {
      if (nextByte == delimiter) {
        items.append(item.toArray)
        item.clear()
      } else {
        item.append(nextByte.toByte)
      }
    }
    items.append(item.toArray)
    items.foreach(item => println(new String(item)))
    bis.close()
  }

}
...