如何读取一个文件作为一个字节数组在 Scala

我可以找到大量的例子,但它们似乎要么主要依赖于 Java 库,要么只是读取字符/行等。

我只是想读入一些文件,得到一个带有 scala 库的字节数组-有人能帮我吗?

70447 次浏览

这应该可以(Scala 2.8) :

val bis = new BufferedInputStream(new FileInputStream(fileName))
val bArray = Stream.continually(bis.read).takeWhile(-1 !=).map(_.toByte).toArray
val is = new FileInputStream(fileName)
val cnt = is.available
val bytes = Array.ofDim[Byte](cnt)
is.read(bytes)
is.close()

你也可以考虑使用 Scalax.io:

scalax.io.Resource.fromFile(fileName).byteArray

Scala.io 源代码有问题,不要在读取二进制文件时使用它。

错误可以按照这里的指示重现: https://github.com/liufengyun/scala-bug

data.bin文件中,它包含十六进制的 0xea,它是二进制的 11101010,应该转换为十进制的 234

main.scala文件包含两种读取文件的方法:

import scala.io._
import java.io._


object Main {
def main(args: Array[String]) {
val ss = Source.fromFile("data.bin")
println("Scala:" + ss.next.toInt)
ss.close


val bis = new BufferedInputStream(new FileInputStream("data.bin"))
println("Java:" + bis.read)
bis.close
}
}

当我运行 scala main.scala时,程序输出如下:

Scala:205
Java:234

Java 库生成正确的输出,而 Scala 库不生成正确的输出。

爪哇7:

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


val byteArray = Files.readAllBytes(Paths.get("/path/to/file"))

我相信这是可能的最简单的方法。只是利用现有的工具在这里。 NIO.2是美妙的。

您可以使用 Apache Commons 压缩 IOUtils

import org.apache.commons.compress.utils.IOUtils


val file = new File("data.bin")
IOUtils.toByteArray(new FileInputStream(file))

我使用下面的代码来读取 CSV 文件。

import scala.io.StdIn.readLine
import scala.io.Source.fromFile


readFile("C:/users/xxxx/Downloads/", "39025968_ccccc_1009.csv")


def readFile(loc :String,filenm :String): Unit ={


var flnm = fromFile(s"$loc$filenm") // Imported fromFile package


println("Files testing")
/*for (line <- flnm.getLines()) {
printf("%4d %s\n", line.length, line)
}*/
flnm.getLines().foreach(println) // getLines() is imported from readLines.
flnm.close()
}

使用 Scala Future 和 JavaNIO2读取异步文件

  def readFile(path: Path)(implicit ec: ExecutionContext): Future[Array[Byte]] = {
val p = Promise[Array[Byte]]()
try {
val channel = AsynchronousFileChannel.open(path, StandardOpenOption.READ)
val buffer = ByteBuffer.allocate(channel.size().toInt);
channel.read(buffer, 0L, buffer, onComplete(channel, p))
}
catch {
case t: Exception => p.failure(t)
}
p.future
}


private def onComplete(channel: AsynchronousFileChannel, p: Promise[Array[Byte]]) = {
new CompletionHandler[Integer, ByteBuffer]() {
def completed(res: Integer, buffer: ByteBuffer): Unit = {
p.complete(Try {
buffer.array()
})
}


def failed(t: Throwable, buffer: ByteBuffer): Unit = {
p.failure(t)
}
}
}