Wenn Ihre Dateien groß sind, lohnt es sich, über die Leistung und den Speicher nachzudenken, wenn Sie sie vollständig in den Speicher einlesen. Wenn das ein Problem ist, ist es am besten, die Dateien als Streams zu behandeln. So würde ich es machen.
Zunächst definieren Ersatztext:
require "stringio"
replacement = StringOI.new <<END
New Title
fff
END
ich dies ein StringIO Objekt gemacht habe, aber es könnte auch ein File-Objekt, wenn Ihr Ersatztext in einer Datei sein.
Öffnen Sie nun Ihre Zieldatei (eine neue Datei) und schreiben Sie jede Zeile aus dem Ersetzungstext hinein.
dest = File.open(dest_fn, 'wb') do |dest|
replacement.each_line {|ln| dest << ln }
Ich dies könnte effizienter gemacht, aber es gibt einen guten Grund, es auf diese Weise zu tun: Jetzt können wir replacement.lineno
nennen die Anzahl der Zeilen ein zweites Mal von Iterieren lesen zu bekommen, statt über sie die zählen Linien.
Als nächstes öffnen Sie die Originaldatei und suchen vor durch gets
replacement.lineno
mal anrufen:
orig = File.open(orig_fn, 'r')
replacement.lineno.times { orig.gets }
schließlich die restlichen Zeilen aus der ursprünglichen Datei in die neue Datei schreiben. Wir werden es tun effizienter dieser Zeit mit File.copy_stream
:
File.copy_stream(orig, dest)
orig.close
dest.close
Das ist es. Natürlich ist es ein Ziehen, diese Dateien manuell zu schließen (und wenn wir es tun, sollten wir es in einem ensure
Block machen), also ist es besser, die Blockform von File.open
zu verwenden, um sie automatisch zu schließen. Außerdem können wir die orig.gets
Anrufe in die replacement.each_line
Schleife bewegen:
File.open(dest_fn, 'wb') do |dest|
File.open(orig_fn, 'r') do |orig|
replacement.each_line {|ln| dest << ln; orig.gets }
File.copy_stream(orig, dest)
end
end
Sie für die Facets Juwel in der Dokumentation verknüpft. Wenn Sie 'File.writelines' verwenden wollen, müssen Sie dieses Juwel installieren. –
@Jordan Gibt es einen eingebauten Weg, dies in Ruby ohne einen Edelstein Dritter zu tun? –
P.S. Der Titel Ihrer Frage sagt "erste zwei Zeilen", aber es sieht so aus, als ob Sie die ersten drei Zeilen ersetzen möchten (eine leere Zeile ist immer noch eine Zeile). FWIW, ein einfacherer Weg, die ersten drei Elemente in einem Array zu ersetzen, ist 'lineArr [0..2] = [" New Title \ n "," \ n "," fff \ n "]' –