Как вставить строку в текстовый файл

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

line1
line2
line3
line4

Новая строка не должна добавляться, а записываться где-то в середине файла. Поэтому я ищу конкретную позицию (или строку) в файле, и когда она была найдена, я вставляю новую строку:

file = File.open(path,"r+")
while (!file.eof?)
  line = file.readline
  if (line.downcase.starts_with?("line1"))
    file.write("Some nice little sentence")
  end
end

Проблема заключается в том, что Ruby перезаписывает строку в этой позиции новым текстом, поэтому результат следующий:

line1
Some nice little sentence
line3
line4

То, что я хочу, является "реальной" вставкой:

line1
Some nice little sentence
line2
line3
line4

Как это можно достичь?

Ответ 1

Если это небольшой файл, я думаю, что самый простой способ:

  • Прочитайте полный файл.
  • Вставьте строку.
  • Запишите новый файл.

Вот как Rails делает это за кулисами.

Или вы можете скопировать его по строкам, а затем перезаписать оригинал с помощью mv следующим образом:

require 'fileutils'

tempfile=File.open("file.tmp", 'w')
f=File.new("file.txt")
f.each do |line|
  tempfile<<line
  if line.downcase=~/^line2/
    tempfile << "Some nice little sentence\n"
  end
end
f.close
tempfile.close

FileUtils.mv("file.tmp", "file.txt")

Ответ 2

def replace(filepath, regexp, *args, &block)
  content = File.read(filepath).gsub(regexp, *args, &block)
  File.open(filepath, 'wb') { |file| file.write(content) }
end


replace(my_file, /^line2/mi) { |match| "Some nice little sentence"}

line1
Some nice little sentence
line2
line3
line4

и если вы хотите добавить к существующему...

replace(my_file, /^line2/mi) do |match| 
  "#{match} Some nice little sentence"
end

line1
line2 Some nice little sentence
line2
line3
line4

Ответ 3

Пара других опций:

file = File.read(path).sub(/line2\n/, 'Some nice little sentence\n\1')
File.write(path, file)

file = File.readlines(path)
index = file.index("line2")
file.insert(index, "Some nice little sentence")
File.write(path, file)

Ответ 4

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

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

Третий подход - записать первую часть в новый файл, записать вставленную строку в новый файл, записать оставшуюся часть исходного файла в новый файл и, наконец, заменить старый файл на новый файл на файловая система. Этот подход позволяет вам работать с одной строкой за раз, чтобы вы могли обрабатывать файлы, которые не вписываются в память.

Причина, по которой это работает, заключается в том, что файл похож на массив с фиксированным размером байтов: когда вы пишете байт в файл, вы перезаписываете существующий байт (я игнорирую случай, когда вы добавляете к файл здесь). Таким образом, единственный способ вставить что-либо в файл - это перенести старый контент в новое место, прочитав его из старого местоположения и записав его в новое место. После этого вы можете "вставить" данные в свободную область.