Невозможно вручную установить номер строки входного потока 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=
перейдет к байтовому смещению, поэтому для этого вам потребуется фиксированная длина строки.
Когда вы думаете об этом, это имеет смысл: поток не может сказать, сколько байтов находится в каждой строке файла, который он еще не прочитал.