Які всі поширені способи читання файлу в Ruby?
Наприклад, ось один метод:
fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
puts(line)
end
fileObj.close
Я знаю, що Рубі надзвичайно гнучка. Які переваги / недоліки кожного підходу?
Які всі поширені способи читання файлу в Ruby?
Наприклад, ось один метод:
fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
puts(line)
end
fileObj.close
Я знаю, що Рубі надзвичайно гнучка. Які переваги / недоліки кожного підходу?
Відповіді:
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
foreach
замість цього open
і не обходиться each_line
блоком.
f.each { |line| ... }
і, f.each_line { |line| ... }
схоже, мають таку саму поведінку (принаймні, у Ruby 2.0.0).
Найпростіший спосіб, якщо файл не надто довгий:
puts File.read(file_name)
Дійсно, IO.read
або File.read
автоматично закриваємо файл, тому немає необхідності використовувати File.open
з блоком.
IO.read
або File.read
також автоматично закривати файл, хоча у вашому формулюванні це звучить так, як ні.
Будьте обережні з "рогалими" файлами. Ось тоді ви читаєте весь файл в пам'ять одразу.
Проблема в тому, що вона не масштабується добре. Ви можете розробити код з файлом досить великого розміру, а потім поставити його у виробництво і раптом виявити, що ви намагаєтесь прочитати файли розміром у гігабайти, і ваш хост заморожується, коли він намагається прочитати та виділити пам'ять.
Лінійний ввід / вивід дуже швидкий і майже завжди такий же ефективний, як і рогатка. Насправді це дивно швидко.
Мені подобається використовувати:
IO.foreach("testfile") {|x| print "GOT ", x }
або
File.foreach('testfile') {|x| print "GOT", x }
Файл успадковується від IO і foreach
знаходиться в IO, тому ви можете використовувати будь-який.
У мене є деякі орієнтири, які показують вплив спроб читання великих файлів через read
вхідний / вивідний рядковий рядок у розділі " Чому" прошивання "файлу не є хорошою практикою? ".
Ви можете прочитати файл одразу:
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 файлів та API IO .
for_each
файлу або IO. Використовуйте foreach
замість цього.
while
замість цього loop
і використовувати ensure
для того, щоб файл закривався, навіть якщо виняток виноситься. Як це (замінити крапку з комою з новим рядком): begin; f = File.open('testfile'); while line = f.gets; puts line; end; ensure; f.close; end
.
Одним з простих методів є використання readlines
:
my_array = IO.readlines('filename.txt')
Кожен рядок у вхідному файлі буде записом у масиві. Метод обробляє відкриття та закриття файлу для вас.
read
і для будь-якого варіанту, і це дозволить перетягнути весь файл у пам'ять, що може спричинити великі проблеми, якщо файл більше, ніж наявна пам'ять. Крім того, оскільки це масив, Ruby повинен створити масив, додатково уповільнивши процес.
file_content = File.read('filename with extension');
puts file_content;
Я зазвичай роблю це:
open(path_in_string, &:read)
Це дасть вам весь текст у вигляді рядкового об’єкта. Він працює лише під Ruby 1.9.
повернути останні n рядків з your_file.log або .txt
path = File.join(Rails.root, 'your_folder','your_file.log')
last_100_lines = `tail -n 100 #{path}`
Ще більш ефективним способом є потокове передавання, попросивши ядро операційної системи відкрити файл, а потім читати байти з нього побіжно. Під час читання файлу на рядок у 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 }
Про це читайте тут у цій детальній публікації:
content = `cat file`
Я думаю, що цей метод є найбільш "незвичайним". Можливо, це щось хитро, але це працює, якщо cat
він встановлений.
content = File.read(filename)