在Scala中编写read-while循环的正确方法是什么?

ARK*_*BAN 26 io scala inputstream

在Scala中编写标准read-while循环的"正确"是什么?正确地说,我的意思是用类似Scala的方式编写而不是类似Java的方式.

这是我在Java中的代码:

MessageDigest md = MessageDigest.getInstance( "MD5" );
InputStream input = new FileInputStream( "file" );
byte[] buffer = new byte[1024];
int readLen;
while( ( readLen = input.read( buffer ) ) != -1 )
    md.update( buffer, 0, readLen );
return md.digest();
Run Code Online (Sandbox Code Playgroud)

这是我在Scala中的代码:

val md = MessageDigest.getInstance( hashInfo.algorithm )
val input = new FileInputStream( "file" )
val buffer = new Array[ Byte ]( 1024 )
var readLen = 0
while( readLen != -1 )
{
    readLen = input.read( buffer )
    if( readLen != -1 )
        md.update( buffer, 0, readLen )
}
md.digest
Run Code Online (Sandbox Code Playgroud)

Scala代码是正确的并且有效,但感觉非常不可靠.首先,它是Java代码的字面翻译,充分利用了Scala的优势.而且它实际上比Java代码长!我真的觉得我错过了什么,但我无法弄清楚是什么.

我对Scala很新,所以我要问这个问题是为了避免陷入在Scala中编写Java风格代码的陷阱.我对Scala解决此类问题的方式比对Scala API可能提供的任何特定帮助方法更感兴趣,以便对文件进行哈希处理.

(我在此问题中提前为我的临时Scala形容词道歉.)

San*_*ozi 28

根据雷克斯的帖子,他提到:

Stream.continually(input.read(buffer)).takeWhile(_ != -1).foreach(md.update(buffer, 0, _))
Run Code Online (Sandbox Code Playgroud)

你应该用它替换var readLen + {...}行,它会产生相同的结果.

正如Rex所说,它适用于scala 2.8.

  • 如果Stream为您提供了意愿,您也可以直接使用Iterator. (2认同)

mic*_*ebe 8

What Rex Kerr suggests in his comment is the following:

val md = MessageDigest.getInstance("MD5")
val input = new FileInputStream("foo.txt")
val buffer = new Array[ Byte ]( 1024 )
Stream.continually(input.read(buffer))
  .takeWhile(_ != -1)
  .foreach(md.update(buffer, 0, _))
md.digest
Run Code Online (Sandbox Code Playgroud)

The key is the Stream.continually. It gets an expression which is evaluated continually, creating an infinite Stream of the evaluated expression. The takeWhile is the translation from the while-condition. The foreach is the body of the while-loop.