2010-10-25 10 views

Respuesta

10

probar una de estas dos soluciones:

file = File.open "file.txt" 

#1 solution would eat a lot of RAM 
p [*file][n-1] 

#2 solution would not 
n.times{ file.gets } 
p $_ 

file.close 
+1

es la solución # 2 Puesta en línea n + 1? –

+0

@ Mark Thomas, en el # 1 también. Supuse indexar desde 0. – Nakilon

+0

Gracias por '[* File.open ('...')]', no sabía que 'to_a' para la instancia de archivo me puede dar sus líneas – tig

18

Se podría conseguirlo por el índice de readlines.

line = IO.readlines("file.txt")[42] 

Utilice solo esto si se trata de un archivo pequeño.

+1

Esta es la respuesta correcta –

+0

Esta es solo la respuesta correcta si el archivo es pequeño, menos de un par de MB. De lo contrario, obligará a Ruby a cargar todo el archivo a la vez, lo que, en el caso de un archivo grande, es más lento que utilizar una solución basada en 'foreach' o' gets'.Ver http://stackoverflow.com/questions/25189262/why-is-slurping-a-file-bad que contiene puntos de referencia. –

+0

¡Me sorprendí al saber que toma tanto como un par de MB! –

3
def get_line_from_file(path, line) 
    result = nil 

    File.open(path, "r") do |f| 
    while line > 0 
     line -= 1 
     result = f.gets 
    end 
    end 

    return result 
end 

get_line_from_file("/tmp/foo.txt", 20) 

Ésta es una buena solución porque:

  • Usted no usa File.read, por lo tanto usted no lee el archivo en la memoria. Si lo hace, podría convertirse en un problema si el archivo es de 20 MB de grande y lee con la suficiente frecuencia para que GC no se mantenga al día.
  • Solo lee desde el archivo hasta la línea que desea. Si su archivo tiene 1000 líneas, obtener la línea 20 solo leerá las 20 primeras líneas en Ruby.

Puede reemplazar gets con readline si desea elevar un error (EOFError) en lugar de volver a cero cuando pasa un fuera de los límites de línea.

+2

Usted escribió en C demasiado tiempo ... – Nakilon

+0

Hehe, eso es lo que obtiene de sus compañeros Ruby cuando intenta escribir un código optimizado ¿eh? :) –

+0

En diferentes idiomas debe optimizar cosas diferentes. – Nakilon

2
linenumber=5 
open("file").each_with_index{|line,ind| 
    if ind+1==linenumber 
    save=line 
    # break or exit if needed. 
    end 
} 

o

linenumber=5 
f=open("file") 
while line=f.gets 
    if $. == linenumber # $. is line number 
    print "#{f.lineno} #{line}" # another way 
    # break # break or exit if needed 
    end 
end 
f.close 

Si lo que desea es obtener la línea y no hace nada más, se puede utilizar este un trazador de líneas

ruby -ne '(print $_ and exit) if $.==5' file 
+0

Agradable. Es entonces cuando las $ variables globales se vuelven útiles. – Nakilon

+0

Esto sigue leyendo el archivo cuando la línea ya está encontrada. – steenslag

+0

No importa. Si el número de línea es la última 2da línea, por ejemplo, tiene que leer hasta esa línea también ... – ghostdog74

1

archivo tiene un buen método lineno.

def get_line(filename, lineno) 
    File.open(filename,'r') do |f| 
    f.gets until f.lineno == lineno - 1 
    f.gets 
    end 
end 
+1

Realmente no necesita lineno(). Puede reemplazar la línea 'hasta' con '(lineno-1) .times {f.gets}'. –

0

Si desea un trazador de líneas y no se preocupan por el gasto de memoria (líneas suponiendo que se numeran del 1)

lineN = IO.readlines('text.txt')[n-1] 

o

lineN = f.readlines[n-1] 

si ya han abierto el archivo .

lo contrario, sería mejor hacerlo de esta manera:

lineN = File.open('text.txt') do |f| 
      (n-1).times { f.gets } # skip lines preceeding line N 
      f.gets     # read line N contents 
     end 
Cuestiones relacionadas