[英]Delete first two lines and add two lines to file
我有一個文本文件,以:
Title
aaa
bbb
ccc
我不知道該行會包含什么,但我知道文件的結構將是Title
,然后是空行,然后是實際行。 我想將其修改為:
New Title
fff
aaa
bbb
ccc
我考慮到了這一點:
lineArray = File.readlines(destinationFile).drop(2)
lineArray.insert(0, 'fff\n')
lineArray.insert(0, '\n')
lineArray.insert(0, 'new Title\n')
File.writelines(destinationFile, lineArray)
但是, writelines
不存在。
`writelines' for File:Class (NoMethodError)
有沒有辦法刪除文件的前兩行添加三個新行?
使用put與整個數組:
File.open("destinationFile", "w+") do |f|
f.puts(lineArray)
end
我會從這樣的事情開始:
NEWLINES = {
0 => "New Title",
1 => "\nfff"
}
File.open('test.txt.new', 'w') do |fo|
File.foreach('test.txt').with_index do |li, ln|
fo.puts (NEWLINES[ln] || li)
end
end
這是運行后test.txt.new
的內容:
New Title
fff
aaa
bbb
ccc
我們的想法是在NEWLINES
哈希中提供替換行列表。 當從原始文件中讀取每一行時,在散列中檢查行號,如果該行存在則使用相應的值,否則使用原始行。
如果你想讀取整個文件然后替換,它會減少代碼,但代碼會有可伸縮性問題:
NEWLINES = [
"New Title",
"",
"fff"
]
file = File.readlines('test.txt')
File.open('test.txt.new', 'w') do |fo|
fo.puts NEWLINES
fo.puts file[(NEWLINES.size - 1) .. -1]
end
它不是很聰明,但它適用於簡單的替換。
如果你真的想要做得對,請學習diff
如何工作,創建差異文件,然后讓它做繁重的工作,因為它是為這類任務設計的,運行速度非常快,並且每天使用數百萬次* nix系統遍布全球。
如果您的文件很大,那么將它們全部讀入內存的性能和內存含義值得考慮。 如果這是一個問題,那么最好的辦法是將文件視為流。 這是我將如何做到這一點。
首先,定義替換文本:
require "stringio"
replacement = StringOI.new <<END
New Title
fff
END
我已經將它變成了一個StringIO對象,但如果替換文本在文件中,它也可以是一個File對象。
現在,打開目標文件(新文件)並將替換文本中的每一行寫入其中。
dest = File.open(dest_fn, 'wb') do |dest|
replacement.each_line {|ln| dest << ln }
我們本可以更有效地完成這項工作,但有一個很好的理由這樣做:現在我們可以調用replacement.lineno
來獲取讀取的行數,而不是再次迭代它來計算行數。
接下來,打開原始文件並通過調用gets
replacement.lineno
次來提前尋找:
orig = File.open(orig_fn, 'r')
replacement.lineno.times { orig.gets }
最后,將原始文件中的剩余行寫入新文件。 我們這次使用File.copy_stream
可以更有效地完成它:
File.copy_stream(orig, dest)
orig.close
dest.close
而已。 當然,這是手動關閉這些文件的拖累(當我們這樣做時,我們應該在一個ensure
塊中執行),所以最好使用File.open
的塊形式來自動關閉它們。 此外,我們可以將orig.gets
調用移動到replacement.each_line
循環中:
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
首先創建一個輸入測試文件。
FNameIn = "test_in"
text = <<_
Title
How now,
brown cow?
_
#=> "Title\n\nHow now,\nbrown cow?\n"
File.write(FNameIn, text)
#=> 27
現在逐行讀寫。
FNameOut = "test_out"
File.open(FNameIn) do |fin|
fin.gets; fin.gets
File.open(FNameOut, 'w') do |fout|
fout.puts "New Title"
fout.puts
fout.puts "fff"
until fin.eof?
fout.puts fin.gets
end
end
end
檢查結果:
puts File.read(FNameOut)
# New Title
#
# fff
# How now,
# brown cow?
當塊終止時,Ruby將關閉這兩個文件中的每一個。
如果文件不大,你可以寫:
File.write(FNameOut,
["New Title\n", "\n", "fff\n"].concat(File.readlines(FNameIn).drop(2)).join)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.