ScalaでInputStreamを文字列に変換する慣用的な方法


111

InputStreamをStringに変換するためにJavaで使用した便利な関数があります。以下は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で行う慣用的な方法はありますか?

回答:


197

Scala> = 2.11の場合

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

Scala <2.11の場合:

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

ほぼ同じことを行います。しかし、なぜラインを取得して、それらをすべて一緒に接着したいのかわからない。ストリームの非ブロッキングを想定できる場合は、単に使用することができます.available、全体をバイト配列に読み取り、そこから直接文字列を作成できます。


2
私が使用した理由の1つは、さまざまなオペレーティングシステムで行末を正規化することです。
Kevin Wright

Raamの答えも素晴らしい(そして少し簡潔な)ですが、例のように具体的になっているため、RexをTHEの答えとしてマークします。行を一緒に接着することは特定のケースで特定のケースでしたが、私はそれを行うのがあまり適切でない場所でこのコードを使用したことを思い出させました。
バラント

ソリューションはgetLines()を使用するため、あまり安全ではありません。入力ストリームに「改行」文字がない場合はどうなりますか?その後、すべてがブロックされます
Paul Sabou 2013年

かなり悪いソリューションです。入力ストリームにDOSの行末(\ r \ n)が含まれている場合はどうなりますか。これらは、このメソッドによって削除されます。また、mkStringはバッファーを使用しますが、文字のブロックを読み取る方が確実に高速です。
Dibbeke 2014年

1
@RexKerr回答で述べた「パフォーマンスのバグ」を指摘してください。いくつかの基本的なテストケースで両方のバージョンをテストしましたが、問題は発生しませんでした。
Sahil Sareen

74

Source.fromInputStream(is).mkString("") 行為も行います.....


いい視点ね; ソースは拡張するものを作成しますIterator[Char]
レックスカー

8
この種のことを行う場合は、文字エンコーディングも指定することをお勧めします。そのために: Source.fromInputStream(is)(Codec.UTF8).mkString
Connor Doyle

これは簡潔ですが、元のJavaコードが閉じたのに対して、ストリームは閉じません。
リッチ

@Richは、fromInputStream()少なくともScala 2.11ではストリームを閉じているようです。
jaco0646

2
@ jaco0646-ストリームを閉じません。テストしたところです。これを証明するデモコードは次のとおり
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メソッドに渡してください。
Kamil Lelonek 2014年

1
これは、Scala 2.11.7のscala.io.Sourceよりも桁違いに速い可能性があります。私はそれの本当に基本的なベンチマークを書きました、そしてほとんどの場合、それは大きなファイル(テストは〜35 MBのテキストファイルでした)の約5%高速で、小さなファイル(テストは〜30 KB)の最大2,800%高速でした。
コリンディーン

2
綺麗な。からの大量の入力を読み取るエレガントなソリューションに苦労してい Runtime.exec()ます。これはそれを釘付けにします。
Pavel Lechev 16

使用する文字セットをどのように指定しますか?
ウィーラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.