Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中编写边读循环的正确方法是什么?_Scala_Inputstream_Io - Fatal编程技术网

在Scala中编写边读循环的正确方法是什么?

在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

在Scala中编写标准的边读边循环的“正确”是什么?我所说的“适当”是指以类似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标准。首先,它是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”中使用它?