2014-04-11 8 views
9

पर अपलोड स्काला में, एक आम दृष्टिकोण, बहुत बड़ी फ़ाइलों के लिएस्काला तेजी से पाठ फ़ाइल पढ़ सकते हैं और एक पाठ फ़ाइल पढ़ने और एक सरणी में यह अपलोड करने के लिए स्मृति

scala.io.Source.fromFile("file.txt").getLines.toArray 

विशेष रूप से है वहाँ एक तेजी से दृष्टिकोण शायद है बाइट्स के ब्लॉक को पहले स्मृति में पढ़कर और फिर उन्हें नए लाइन वर्णों से विभाजित करके? (आमतौर पर उपयोग किए जाने वाले दृष्टिकोणों के लिए Read entire file in Scala देखें।)

बहुत धन्यवाद।

+2

ध्यान दें कि 'स्रोत' 'बुफर्डसोर्स' का उपयोग करता है, जो बदले में जावा के 'बुफर्ड रीडर' का उपयोग करता है। तो यह पहले से ही स्मृति के डेटा को स्मृति में पढ़ता है - यह बाइट-बाय-बाइट नहीं पढ़ता है। – DNA

+0

@ डीएनए अवलोकन के लिए बहुत धन्यवाद, यह सोचकर कि क्या (यहां तक ​​कि) तेजी से दृष्टिकोण हैं, शायद java.nio के साथ ... – elm

+1

कृपया, * बहुत बड़ी फाइलें परिभाषित करें * और आप उस डेटा के साथ क्या करने जा रहे हैं (विभाजन के बाद यह लाइनों में) –

उत्तर

19

प्रदर्शन समस्या के डेटा को पढ़ने के तरीके से कोई लेना देना नहीं है। यह पहले से ही buffered है। कुछ नहीं होता जब तक आप वास्तव में लाइनों के माध्यम से पुनरावृति:

// measures time taken by enclosed code 
def timed[A](block: => A) = { 
    val t0 = System.currentTimeMillis 
    val result = block 
    println("took " + (System.currentTimeMillis - t0) + "ms") 
    result 
} 

val source = timed(scala.io.Source.fromFile("test.txt")) // 200mb, 500 lines 
// took 0ms 

val lines = timed(source.getLines) 
// took 0ms 

timed(lines.next) // read first line 
// took 1ms 

// ... reset source ... 

var x = 0 
timed(lines.foreach(ln => x += ln.length)) // "use" every line 
// took 421ms 

// ... reset source ... 

timed(lines.toArray) 
// took 915ms 

प्रति मेरी हार्ड ड्राइव के लिए दूसरा 500MB का रीड-गति को देखते हुए, इष्टतम समय 200MB, जिसका अर्थ है के लिए कोई जगह नहीं है कि के लिए 400 मि.से पर होगा इटरेटर को एक सरणी में परिवर्तित करने के अलावा अन्य सुधार।

आपके आवेदन के आधार पर आप सीधे ऐरे के बजाय इटरेटर का उपयोग करने पर विचार कर सकते हैं। क्योंकि मेमोरी में इतनी बड़ी सरणी के साथ काम करना निश्चित रूप से एक प्रदर्शन मुद्दा होगा।


संपादित: अपनी टिप्पणी मुझे लगता है, कि आप आगे सरणी बदलना चाहते से (शायद स्तंभों में लाइनों विभाजित के रूप में आप ने कहा कि आप एक संख्यात्मक सरणी पढ़ रहे हैं)। उस स्थिति में मैं पढ़ने के दौरान परिवर्तन करने की सलाह देते हैं। उदाहरण के लिए:

source.getLines.map(_.split(",").map(_.trim.toInt)).toArray 

source.getLines.toArray.map(_.split(",").map(_.trim.toInt)) 

(मेरे लिए यह 1.9s बजाय 2.5S है) की तुलना में काफी तेजी से क्योंकि आप दूसरे में एक पूरे विशाल सरणी को बदलने नहीं है, लेकिन सिर्फ प्रत्येक पंक्ति है व्यक्तिगत रूप से, एक एकल सरणी में समाप्त होता है (केवल आधा हीप स्पेस का उपयोग करता है)। फ़ाइल को पढ़ने के बाद भी एक बाधा है, पढ़ने के दौरान बदलना लाभ होता है जिससे इसका बेहतर CPU उपयोग होता है।

+0

अवलोकनों के लिए बहुत धन्यवाद, वास्तव में लायक; समस्या में अभी भी आवश्यक है फ़ाइल को प्रति पंक्ति के आधार पर फ़ाइल को प्रोसेस करने से परे, स्मृति में फ़ाइल अपलोड करने की आवश्यकता है। – elm

+0

ग्रेट उत्तर। –

+0

@ user3189923 के रूप में चिह्नित किया जाना चाहिए कुछ और जानकारी के लिए मेरा संपादन देखें ... –

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