我有一个以:
开头的文本文件Title
aaa
bbb
ccc
我不知道该行会包含什么,但我知道该文件的结构为Title
,然后是空行,然后是实际行。我想将其修改为:
New Title
fff
aaa
bbb
ccc
我记得this:
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)
有没有办法删除文件的前两行并添加三行?
答案 0 :(得分:1)
对整个数组使用put:
File.open("destinationFile", "w+") do |f|
f.puts(lineArray)
end
答案 1 :(得分:1)
我会从这样的事情开始:
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系统上进行数百万次。
答案 2 :(得分:1)
如果您的文件很大,那么将它们全部读入内存的性能和内存含义值得考虑。如果这是一个问题,那么最好的办法是将文件视为流。我就是这样做的。
首先,定义替换文字:
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
答案 3 :(得分:0)
首先创建一个输入测试文件。
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)