2010-06-10 20 views
24

什麼是在Scala中編寫標準讀取while循環的「正確」?正確的說,我的意思是用類似斯卡拉的方式寫成,而不是類似Java的方式。什麼是在Scala中編寫read-while循環的正確方法?

這裏是我在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(); 

這裏是我在斯卡拉代碼:

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代碼是正確的,工作的,但感覺非常不斯卡拉-ish。首先,它是Java代碼的直譯,充分利用了Scala的優勢。而且它實際上比Java代碼更長!我真的覺得我失去了一些東西,但我無法弄清楚什麼。

我對Scala相當陌生,所以我提出這個問題以避免陷入編寫Java風格代碼的陷阱。我對Scala方法更感興趣,以解決這種問題,而不是Scala API提供的用於散列文件的特定輔助方法。

(我提前在整個這一問題表示歉意我的特設斯卡拉形容詞。)

+4

我對http://stackoverflow.com/questions/2849303的回答可能會有所幫助。 – 2010-06-10 02:38:21

+5

@Rex我會使用'Iterator'而不是'Stream'。畢竟,它是一次性的,不可重複使用。此外,'Iterator'在這些任務中具有更好的內存性能。 – 2010-06-10 20:37:27

+0

@丹尼爾 - 同意。我相信有一個很好的理由,爲什麼我之前使用'Stream',但我不能再記得什麼(我認爲它仍然是真的)。無論如何,這裏'Iterator.continually'應該沒問題。 – 2010-06-10 22:10:17

回答

25

基於Rex的職位,他提到:

Stream.continually(input.read(buffer)).takeWhile(_ != -1).foreach(md.update(buffer, 0, _)) 

此時應更換VAR readLen +,而{.. 。}與它一致,它會產生相同的結果。

正如雷克斯提到的,它適用於scala 2.8。

+2

如果Stream給了你willies,你也可以直接使用Iterator.continuous。 – 2011-02-26 21:01:12

+0

當我在Process中得到的InputStream上嘗試它時,foreach方法只是調用第一個字符,然後停止。與while一起使用時,我可以獲得所有數據。任何想法爲什麼? – pommedeterresautee 2013-12-08 11:17:42

+0

如何獲得從「input.read(...)」中讀取的字節數以在「foreach」中使用它? – 2014-08-09 06:23:45

7

什麼雷克斯科爾暗示在他的評論如下:

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條件翻譯的條件。 foreachwhile -loop的主體。

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 

iterateStream第3行,你可以添加到庫中的函數是:

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解決方案更簡單。

相關問題