簡體   English   中英

刪除前兩行並在文件中添加兩行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM