在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();
以下是我在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
Scala代码是正确的并且有效,但感觉非常不符合Scala-ish。首先,它是Java代码的字面翻译,充分利用了Scala的优势。而且它实际上比Java代码长!我真的觉得我错过了什么,但我无法弄清楚是什么。
我对Scala相当陌生,因此我提出的问题是避免陷入在Scala中编写Java风格代码的陷阱。我对Scala解决此类问题的方式比对Scala API提供的任何特定帮助方法更感兴趣,以便对文件进行哈希处理。
(我在此问题中提前为我的临时Scala形容词道歉。)
答案 0 :(得分:28)
根据雷克斯的帖子,他提到:
Stream.continually(input.read(buffer)).takeWhile(_ != -1).foreach(md.update(buffer, 0, _))
你应该用它替换var readLen + {...}行,它会产生相同的结果。
正如Rex所说,它适用于scala 2.8。
答案 1 :(得分:8)
Rex Kerr在评论中建议如下:
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
关键是Stream.continually
。它得到一个连续计算的表达式,创建一个计算表达式的无限Stream
。 takeWhile
是来自while
条件的翻译。 foreach
是while
- 循环的主体。
答案 2 :(得分:0)
咖喱功能怎么样?你有11行Scala代码:
val md = MessageDigest.getInstance(hashInfo.algorithm)
val input = new FileInputStream("file")
iterateStream(input){ (data, length) =>
md.update(data, 0, length)
}
md.digest
第3行的iterateStream
函数可以添加到库中:
def iterateStream(input: InputStream)(f: (Array[Byte], Int) => Unit){
val buffer = new Array[Byte](512)
var curr = input.read(buffer)
while(curr != -1){
f(buffer, curr)
curr = input.read(buffer)
}
}
丑陋的重复代码(读取输入的地方)最终出现在库中,经过充分测试并远离程序员。我觉得第一个代码块没有Iterator.continually
解决方案那么复杂。