Каковы все распространенные способы чтения файлов в Ruby? - PullRequest
266 голосов
/ 05 апреля 2011

Каковы все распространенные способы чтения файлов в Ruby?

Например, вот один метод:

fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
  puts(line)
end
fileObj.close

Я знаю, что Ruby чрезвычайно гибок.Каковы преимущества / недостатки каждого подхода?

Ответы [ 10 ]

299 голосов
/ 05 апреля 2011

Самый простой способ, если файл не слишком длинный:

puts File.read(file_name)

Действительно, IO.read или File.read автоматически закрывают файл, поэтому нет необходимости использовать File.open сблок.

249 голосов
/ 05 апреля 2011
File.open("my/file/path", "r") do |f|
  f.each_line do |line|
    puts line
  end
end
# File is closed automatically at end of block

Также возможно явно закрыть файл после того, как указано выше (передать блок в open, чтобы он закрылся для вас):

f = File.open("my/file/path", "r")
f.each_line do |line|
  puts line
end
f.close
215 голосов
/ 05 апреля 2011

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

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

Построчный ввод-вывод очень быстрый и почти всегда такой же эффективный, как прихлебывание.На самом деле это удивительно быстро.

Мне нравится использовать:

IO.foreach("testfile") {|x| print "GOT ", x }

или

File.foreach('testfile') {|x| print "GOT", x }

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

У меня есть несколько тестов, показывающих влияние попытки чтения больших файлов с помощью read по сравнению с построчным вводом / выводом в «. Почему« бродит »файл нехорошая практика?".

68 голосов
/ 15 июня 2014

Вы можете прочитать файл сразу:

content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}

Когда файл большой или может быть большим, обычно лучше обрабатывать его построчно:

File.foreach( 'file.txt' ) do |line|
  puts line
end

Иногда вам нужен доступ к дескриптору файла или контроль чтения:

File.open( 'file.txt' ) do |f|
  loop do
    break if not line = f.gets
    puts "#{f.lineno}: #{line}"
  end
end

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

File.open('file.bin', 'rb') do |f|
  loop do
    break if not buf = f.gets(nil, 80)
    puts buf.unpack('H*')
  end
end

Наконец, вы можете сделать это без блока, например, при обработке нескольких файлов одновременно. В этом случае файл должен быть явно закрыт (улучшен согласно комментарию @antinome):

begin
  f = File.open 'file.txt'
  while line = f.gets
    puts line
  end
ensure
  f.close
end

Ссылки: Файловый API и IO API .

25 голосов
/ 05 апреля 2011

Один простой способ - использовать readlines:

my_array = IO.readlines('filename.txt')

Каждая строка во входном файле будет записью в массиве.Метод обрабатывает открытие и закрытие файла для вас.

19 голосов
/ 26 августа 2016
file_content = File.read('filename with extension');
puts file_content;

http://www.ruby -doc.org / ядро-1.9.3 / IO.html # способ-с чтения

9 голосов
/ 05 апреля 2011

Я обычно делаю это:

open(path_in_string, &:read)

Это даст вам весь текст в виде строкового объекта.Работает только под Ruby 1.9.

4 голосов
/ 06 апреля 2016

возвращает последние n строки из your_file.log или .txt

path = File.join(Rails.root, 'your_folder','your_file.log')

last_100_lines = `tail -n 100 #{path}`
0 голосов
/ 12 ноября 2018
content = `cat file`

Я думаю, что этот метод является наиболее "необычным". Может быть, это немного сложно, но работает, если установлена ​​cat.

0 голосов
/ 06 октября 2018

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

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

Пример:

Добавление этого класса в ваше приложение в качестве объекта службы:

class MyIO
  def initialize(filename)
    fd = IO.sysopen(filename)
    @io = IO.new(fd)
    @buffer = ""
  end

  def each(&block)
    @buffer << @io.sysread(512) until @buffer.include?($/)

    line, @buffer = @buffer.split($/, 2)

    block.call(line)
    each(&block)
  rescue EOFError
    @io.close
 end
end

Вызовите его и передайте :each метод блока:

filename = './somewhere/large-file-4gb.txt'
MyIO.new(filename).each{|x| puts x }

Прочтите об этом здесь в этом подробном сообщении:

Ruby Magic Slurping & Streaming Files By AppSignal

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...