Невозможно вручную установить номер строки входного потока stdin, используя ARGF.lineno=

Я пытаюсь прочитать файл через ARGF и выполнить некоторые операции с ним. Прежде чем делать что-либо еще, мне нужно прочитать определенную строку и проверить ее содержание.

Я называю свой сценарий так:

./main.rb < input.txt

Я пытаюсь получить доступ к конкретной строке (скажем, строка 10) следующим образом:

if __FILE__ == $0

    ARGF.lineno= 10
    puts "lineno: #{ARGF.lineno}" # Prints 10 (as expected)
    puts "readline: #{ARGF.readline}" # Prints contents of line 0 instead of 10!

end

Я могу вручную установить ARGF.lineno= для документов, и это, кажется, работает. Однако когда я пытаюсь прочитать только что установленную строку, я получаю содержимое строки 0. Что, если что-то я делаю неправильно?

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

Заранее благодарю за любую помощь.

2 ответа

Решение

Если вы посмотрите на источник для lineno= метод, вы увидите, что он никак не влияет на поток ввода - он просто перезаписывает автоматический номер строки с заданным значением. Если вы хотите перейти к определенной строке, вам нужно написать свой собственный метод.

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

Например:

def ARGF.skip_lines num
  enum = each_line
  num.times { enum.next }
  self
end

Я проверил это с файлом 36M с 600000 строк, и он мог пропустить от первой до последней строки примерно за 1 секунду.

Если у вас есть контроль над форматом ввода, вы можете заполнить каждую строку определенной длиной, а затем использовать IO#seek перейти к определенному. Но у этого есть и другие недостатки.

Вы хотите использовать pos= сбруя: lineno= похоже, ничего не делает в соответствии с документами.

pos= перейдет к байтовому смещению, поэтому для этого вам потребуется фиксированная длина строки.

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

Другие вопросы по тегам