在Scala中将InputStream转换为字符串的惯用方式


110

我有一个方便的函数,已在Java中使用过,用于将InputStream转换为String。这是Scala的直接翻译:

  def inputStreamToString(is: InputStream) = {
    val rd: BufferedReader = new BufferedReader(new InputStreamReader(is, "UTF-8")) 
    val builder = new StringBuilder()    
    try {
      var line = rd.readLine 
      while (line != null) { 
        builder.append(line + "\n")
        line = rd.readLine
      }
    } finally {
      rd.close
    }
    builder.toString
  }

在Scala中有惯用的方法吗?

Answers:


196

对于Scala> = 2.11

scala.io.Source.fromInputStream(is).mkString

对于Scala <2.11:

scala.io.Source.fromInputStream(is).getLines().mkString("\n")

做几乎相同的事情。不确定为什么要弄线,然后将它们重新粘在一起。如果可以假定流是非阻塞的,则可以使用.available,将整个内容读取到字节数组中,然后直接从中创建一个字符串。


2
我用过一个可能的原因,是对不同操作系统上的行尾进行规范化。
凯文·赖特

Raam的答案也很棒(并且更为简洁),但是将Rex标记为THE答案,因为它更具体地类似于示例。在某些情况下,将线粘在一起是特定的,但是您提醒我,我在不太适合这样做的地方使用了此代码。
2011年

该解决方案不是很安全,因为它使用getLines(); 如果输入流没有“换行”字符怎么办?然后整个事件都被阻止了
Paul Sabou 2013年

相当糟糕的解决方案。如果输入流包含DOS行尾(\ r \ n),该怎么办。这些将通过此方法删除。另外,尽管mkString使用缓冲区,但肯定可以更快地读取字符块。
Dibbeke 2014年

1
@RexKerr您能否指出您在答案中提到的“性能错误”。我用一些基本的测试用例测试了这两个版本,没有遇到任何问题。
Sahil Sareen

74

Source.fromInputStream(is).mkString("") 也会做事的.....


好点子; 源创建扩展的东西Iterator[Char]
Rex Kerr

8
通常,在执行此类操作时也要指定字符编码。为此: Source.fromInputStream(is)(Codec.UTF8).mkString
Connor Doyle 2013年

这很简洁,但是它不会关闭流,而原始的Java代码会关闭。
Rich

@Rich,fromInputStream()似乎至少在Scala 2.11中关闭了流。
jaco0646 '16

2
@ jaco0646-它不会关闭流。我刚刚测试。这是证明它的演示代码:gist.github.com/RichardBradley/bcd1a5e61fcc83e4e59f8b9b0bc2301c
Rich

13

更快的方法:

    private def inputStreamToString(is: InputStream) = {
        val inputStreamReader = new InputStreamReader(is)
        val bufferedReader = new BufferedReader(inputStreamReader)
        Iterator continually bufferedReader.readLine takeWhile (_ != null) mkString
    }

“快点”?但是当我只有一个Reader而不是一个时,它为我提供了解决方法的答案InputStream
BeepDog 2014年

3
只需跳过第一行,然后传递inputStreamReader给方法即可。
卡米尔·莱洛内克

1
这可能比Scala 2.11.7中的scala.io.Source快一个数量级。我写了一个非常基本的基准测试,在大多数情况下,大文件(测试约为35 MB文本文件)的速度大约提高了5%,小文件(测试约为30 KB)的速度提高了约2,800% 。
Colin Dean

2
美丽。一直在努力寻求一种优雅的解决方案,以读取来自的大量输入 Runtime.exec()。这钉它。
帕维尔·莱切夫

如何指定要使用的字符集?
惠勒
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.