在Scala中编写边读循环的正确方法是什么?
在Scala中编写标准的边读边循环的“正确”是什么?我所说的“适当”是指以类似Scala的方式编写,而不是以类似Java的方式编写 以下是我用Java编写的代码:在Scala中编写边读循环的正确方法是什么?,scala,inputstream,io,Scala,Inputstream,Io,在Scala中编写标准的边读边循环的“正确”是什么?我所说的“适当”是指以类似Scala的方式编写,而不是以类似Java的方式编写 以下是我用Java编写的代码: MessageDigest md = MessageDigest.getInstance( "MD5" ); InputStream input = new FileInputStream( "file" ); byte[] buffer = new byte[1024]; int readLen; while( ( readLen
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标准。首先,它是Java代码的直译,没有利用Scala的任何优点。而且它实际上比Java代码长!我真的觉得我错过了什么,但我不知道是什么
我对Scala相当陌生,所以我提出这个问题是为了避免落入在Scala中编写Java风格代码的陷阱。我更感兴趣的是Scala解决这类问题的方法,而不是Scala API为散列文件提供的任何特定助手方法
(我为我在整个问题中的特殊Scala形容词提前道歉。)根据Rex的帖子,他提到:
Stream.continually(input.read(buffer)).takeWhile(_ != -1).foreach(md.update(buffer, 0, _))
您应该替换var readLen+,而{…}行则会产生相同的结果
正如Rex提到的,它与scala 2.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
关键是
流。持续。它获取一个不断求值的表达式,创建求值表达式的无限流。takeWhile
是对while
-条件的翻译。foreach
是while
循环的主体。一个curried函数呢?您可以将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)
}
}
丑陋的重复代码(读取输入的地方)最终进入库中,经过良好测试并隐藏在程序员面前。我觉得第一个代码块没有迭代器复杂。不断地
解决方案。我的答案可能会有帮助。@Rex我会使用迭代器
而不是流
。毕竟,它是一次性的,不可重复使用。此外,Iterator
在此类任务中具有更好的内存性能。@Daniel-同意。我相信我以前使用Stream
有一个很好的理由,但我再也记不起是什么了(我也不认为这仍然是真的)。不管怎样,这里的Iterator.continuously
应该可以。如果流让您感到不安,您也可以直接使用Iterator.continuouse。当我在从进程获得的InputStream上尝试它时,foreach方法只会为第一个字符调用,然后停止。当与while一起使用时,我获得所有数据。知道为什么吗?我如何获得从“input.read(…)”读取的字节数,以便在“foreach”中使用它?