如何在Scala中将文件读取为字节数组


77

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

我只想读一些文件并获得带有Scala库的字节数组-有人可以帮我吗?


3
我认为每个人都会(几乎包括?)依靠Java库,包括Scala库。例如,请参见scala.io.Source的源代码。
菲利普

2
您并没有使用其他语言,仅是一种标准的JVM API,事实证明它足够好,不需要替换!
Duncan McGregor

4
那么,您如何看待Java类的实现?在某个地方的深处,有一个本机方法:它只有一个签名,没有Java实现,并且依赖于特定于OS的C实现。那不是作弊吗?:)
Philippe

2
应该说,.Net上的Scala确实使这成为一个更加紧迫的问题。
Duncan McGregor

4
@Philippe:当然,使用C只是在汇编程序上作弊:P ...我的意思是,通常很清楚地定义语言之间的边界,Scala和Java相互融合。
fgysin恢复莫妮卡2011年

Answers:



45

这应该起作用(Scala 2.8):

val bis = new BufferedInputStream(new FileInputStream(fileName))
val bArray = Stream.continually(bis.read).takeWhile(-1 !=).map(_.toByte).toArray

我认为这是包装Java API函数以获得Stream语义的一个很好的例子。非常感激。
qu1j0t3

3
val bis = new java.io.BufferedInputStream(new java.io.FileInputStream(fileName)); 如果您没有导入Java路径
BeniBela 2013年

1
使用这种方法,是否还需要关闭文件还是隐式的?
最多

1
您需要
Tony K.

13
这种方法很慢,因为它需要处理每个字节。理想情况下,I / O操作应基于块。
Dibbeke

6
val is = new FileInputStream(fileName)
val cnt = is.available
val bytes = Array.ofDim[Byte](cnt)
is.read(bytes)
is.close()

1
这不是有效的解决方案。来自InputStream.java的javadoc:Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.
m.bemowski

5

scala.io.Source有问题,请勿在读取二进制文件时使用它。

可以按照此处的指示重现该错误: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库不会。


10
如果将编码设置为Source.fromFile("data.bin", "ISO8859-1"),则效果很好。
刘凤云2014年

6
也许有帮助,但实际上,这不是答案。在答案中引入新问题不是建设性的,而是属于其他地方的。
本杰明


2

您可以使用Apache Commons Compress IOUtils

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

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

1
我必须导入导入org.apache.commons.io.IOUtils而不是建议的导入。
niid

0

我已使用以下代码读取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() 
}

1
提早回答这个问题(已有9多年的历史了),并且已经提交了许多答案,这有助于指出您的新答案与以前的答案有何不同。(并且包括被注释掉的代码看起来很草率。)
jwvh,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.