Выборочный файл, читаемый в Ruby - PullRequest
3 голосов
/ 14 июня 2011

У меня есть огромный файл, который выглядит следующим образом:

7

bla1
blala
blabla
blab
blals
blable
bla

more here..

Первые числа показывают, сколько значений у меня будет.Дело в том, что я просто хочу указать прямо на строку 11 (текст «больше здесь ..»), без необходимости читать все эти значения раньше.В моем случае у меня большое количество цифр, поэтому оно должно быть оптимизировано.

Вы бы мне что-нибудь порекомендовали?

Ответы [ 4 ]

5 голосов
/ 14 июня 2011

Возможно, вы могли бы использовать File # seek для случайного доступа к файлу.

Проблема этого подхода в том, что он будет просто обращаться к данным с заданным байтовым смещением, а не смещением строки,Если ваш файл может дать смещение байта в начале файла до конца списка, вы можете использовать это.

3 голосов
/ 14 июня 2011

Вы можете сделать что-то подобное файлу, которое пропустит первые N строк:

SkipFile.open("/tmp/frarees") do |ln|
  puts ln                                   # "more here.." and so on
end

puts SkipFile.new("/tmp/frarees").readline  # "more here.."

Вот так:

class SkipFile
  def self.open(fn, &block)
    sf = SkipFile.new(fn)
    return sf unless block
    sf.each(&block)
  end

  def initialize(fn)
    @f = File.open(fn)
    skip = @f.readline.to_i     # Skip N lines as prescribed by the file
    skip.times { @f.readline }  # this could be done lazily
  end

  def each(&block)
    @f.each(&block)
  end

  def readline
    @f.readline
  end
end

Легко сделать, если вы просто хотите перебрать строки файла. Однако становится утомительно, если вы хотите точно имитировать интерфейс File или IO (но см. Delegate) и особенно если вы хотите поддержать перемотку назад к фиктивному началу вашего файла .

1 голос
/ 15 июня 2011

Не думаю, что вы добьетесь большей эффективности, чем эта, поскольку вы прочитали байты в файле, чтобы выяснить, что такое "строка".

f = File.open('./data')
(f.readline.to_i + 2).times { f.readline }
p f.readline
1 голос
/ 14 июня 2011

Вот элегантный способ сделать это, вероятно, не очень эффективный, хотя он требует загрузки всего файла в память сразу.

File.readlines(file_path)[10..-1] # indexing starts from 0
...