2015-06-10 11 views
6

मैं स्काला में एक बड़ी फ़ाइल को पढ़ने और कश्मीर बिट्स के ब्लॉकों में इसे संसाधित (k 65536 आम तौर पर हो सकता है) की जरूरत है। एक साधारण उदाहरण के रूप (लेकिन मैं क्या चाहते हैं):पढ़ना बहुत बड़ी फ़ाइलों (~ 1 टीबी) अनुक्रमिक ब्लॉक में

फ़ाइल ब्लॉक (f1, f2, ... fk) हैं।

मैं गणना करने के लिए केवल लगातार भंडारण और अन्य ब्लॉकों की जरूरत के बिना वर्तमान ब्लॉक का उपयोग SHA256(f1)+SHA256(f2)+...+ SHA256(fk)

इस तरह की एक गणना संवर्द्धित किया जा सकता है चाहता हूँ।

फ़ाइल पढ़ने का सबसे अच्छा तरीका क्या है? (शायद कुछ निरंतरता का उपयोग करता है?)

संपादित करें: जुड़ा हुआ सवाल तरह की समस्या का हल नहीं है लेकिन हमेशा की तरह, फ़ाइल के रूप में मैं देख रहा हूँ पर बाइनरी डेटा है।

+0

@Christian, नहीं, यह सवाल उद्धृत की नकल नहीं है पैदा करता है। – Biswanath

+0

मैं समझ नहीं पा रहा हूं कि यह उद्धृत प्रश्न के साथ एक डुप्लिकेट कैसे है। दूसरा प्रश्न टेक्स्ट आधारित सीएसवी फ़ाइल के बारे में बात करता है, यह प्रश्न "टेक्स्ट आधारित सीएसवी" फ़ाइल से निपट रहा है। अन्य प्रश्न के उत्तर लागू नहीं होना चाहिए। मैं वास्तव में संदेह करता हूं कि इसे कभी भी डुप्लिकेट के रूप में चिह्नित किया गया है यदि वे दोनों प्रश्नों को पूरी तरह से पढ़ते हैं। – Biswanath

उत्तर

4

यहां अक्का स्ट्रीम का उपयोग करने का एक दृष्टिकोण है। यह निरंतर स्मृति का उपयोग करता है और फ़ाइल फ़ाइलों को पढ़ने के रूप में संसाधित कर सकता है।

अधिक जानकारी के लिए इस पृष्ठ के नीचे "स्ट्रीमिंग फ़ाइल IO" देखें। http://doc.akka.io/docs/akka-stream-and-http-experimental/1.0-RC3/scala/stream-io.html

एक सरल build.sbt फ़ाइल के साथ प्रारंभ:

scalaVersion := "2.11.6" 

libraryDependencies ++= Seq(
     "com.typesafe.akka" %% "akka-stream-experimental" % "1.0-RC3" 
) 

दिलचस्प भागों Source, Flow, और Sink हैं। Source एक SynchronousFileSource है जो 65536 के एक खंड आकार के साथ एक बड़ी फ़ाइल में पढ़ता है। ByteString खंड आकार का Source से उत्सर्जित किया गया है और Flow से उपभोग किया गया है जो प्रत्येक खंड के लिए SHA256 हैश की गणना करता है। अंत में, SinkFlow से आउटपुट का उपभोग करता है और बाइट सरणी प्रिंट करता है। आप कुल योग प्राप्त करने के लिए इन्हें परिवर्तित करना चाहते हैं और उन्हें fold का उपयोग करके जोड़ना चाहते हैं।

import akka.stream.io._ 
import java.io.File 
import scala.concurrent.Future 
import akka.stream.scaladsl._ 
import akka.actor.ActorSystem 
import akka.stream.ActorFlowMaterializer 
import java.security.MessageDigest 

object LargeFile extends App{ 
    implicit val system = ActorSystem("Sys") 
    import system.dispatcher 
    implicit val materializer = ActorFlowMaterializer() 

    val file = new File("<path to large file>") 

    val fileSource = SynchronousFileSource(file, 65536) 

    val shaFlow = fileSource.map(chunk => sha256(chunk.toString)) 

    shaFlow.to(Sink.foreach(println(_))).run//TODO - Convert the byte[] and sum them using fold 

    def sha256(s: String) = { 
    val messageDigest = MessageDigest.getInstance("SHA-256") 
    messageDigest.digest(s.getBytes("UTF-8")) 
    } 
} 

BYTE ARRAYS!

> run 
[info] Running LargeFile 
[[email protected] 
[[email protected] 
[[email protected] 
... 
0

लगातार धारा का उपयोग कर डाइजेस्ट बनाना है, जो मेरा मानना ​​है कि एक इटरेटर

import java.File 
import java.FileInputStream 
import java.security.MessageDigest 

val file = new File("test.in") 
val is = new FileInputStream(file) 

val md = MessageDigest.getInstance("SHA-256") 

val bytes = Array.fill[Byte](65536)(0) 

Stream 
    .continually((is.read(bytes),bytes)) 
    .takeWhile(_._1 != -1) 
    .foreach{ x => md.update(x._2,0,x._1) } 

println(md.digest()) 
// prinln(md.digest().map("%02X" format _).mkString) // if you want hex string 
+0

cala.collection.immutable.Stream को याद किया जाता है, जो पूरी चीज को स्मृति में पढ़ेगा (http://stackoverflow.com/questions/4255021/how-do-i-read-a-large-csv-file- साथ-स्केला धारा स्तरीय # जवाब-4255338) – mikebridge

संबंधित मुद्दे