2014-04-11 15 views
9

yüklemek, ortak bir yaklaşım, çok büyük dosyalar içinScala hızlı metin dosyası okumak ve bir metin dosyası okuma ve bir dizi içerisine yüklemek için, Scala olarak belleğe

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

Özellikle bir hızlı yaklaşım belki orada önce bayt bloklarını önce belleğe okuyarak ve sonra yeni satır karakterleriyle ayırarak? (Sık kullanılan yaklaşımlar için bkz. Read entire file in Scala.)

Çok teşekkürler.

+2

Not: Kaynak ''' '' '' BufferedSource' kullanır, bu da Java'nın 'BufferedReader' kullanır. Bu yüzden zaten veri bloklarını belleğe okur - bayt-byte okumaz. – DNA

+0

@DNA, gözlem için çok teşekkürler, belki de java.nio ... – elm

+1

ile daha hızlı yaklaşımlar olup olmadığını merak ediyorum, * çok büyük dosyaları * tanımlayın ve bu verilerle ne yapacağınızı (bölmeden sonra) satırlar halinde) –

cevap

19

Performans sorununun, verilerin okunma şekliyle hiçbir ilgisi yoktur. Bu zaten tamponlu. Aslında hatları boyunca yineleme kadar hiçbir şey olmaz:

// 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 

benim sabit sürücünün saniyede 500MB salt hız göz önüne alındığında, en uygun zaman yer yoktur demektir 200MB için 400 ms olacağını yineleyiciyi bir diziye dönüştürmüyor dışındaki gelişmeler.

Uygulamanıza bağlı olarak, bir Dizi yerine doğrudan yineleyici kullanmayı düşünebilirsiniz. Çünkü hafızada böyle büyük bir dizi ile çalışmak kesinlikle bir performans sorunu olacaktır.


Düzenleme: Ben daha fazla dizi dönüştürmek istediğiniz, varsayalım yorumlarınızı itibaren (eğer sayısal bir dizi okurken söylediği gibi belki sütunlara çizgileri bölünmüş). Bu durumda okuma sırasında dönüşüm yapmayı tavsiye ederim. Örneğin:

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

başka içine bütün bir dev dizi dönüşümü olmadığı için (o 1.9s yerine 2.5s olan Benim için)

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

çok daha hızlıdır ancak sadece her çizgidir tek bir dizide bitenler (yığın alanının yalnızca yarısını kullanır). Ayrıca, dosya okunurken bir darboğaz olduğu için okuma sırasında dönüştürme işlemi daha iyi bir CPU kullanımıyla sonuçlanır.

+0

Çok Gerçekten gözlemler için teşekkürler; Ancak problemin asıl sebebi dosyayı bir dosya üzerinde işlemenin ötesinde belleğe yükleme ihtiyacıdır. – elm

+0

Harika cevap. Doğru olarak işaretlenmelidir –

+0

@ user3189923 Daha fazla bilgi için benim düzenleme bölümüne bakın ... –