我正在尝试更改现有文件的内容。我有这段代码,它有效。但是我希望找到一种更好的方法来打开文件的一次操作。
File.open(file_name , 'r') do |f|
content = f.read
end
File.open(file_name , 'w') do |f|
content.insert(0, "something ")
f.write(content)
end
我们有办法只打开一次文件吗?
我尝试使用File.open(file_name , 'r+')
,它似乎只附加到文件的末尾(无法在文件的开头插入内容)。
答案 0 :(得分:1)
[编辑:我错过了您的问题,但我的代码可以通过简单地插入一行修复:
text_to_prepend = ''
后
line_out = text_to_prepend + buf.shift
它可以简化一点(对于你的问题),但我会保留它,以显示如何将相同的字符串添加到每一行。]
你可以打开文件但是一次,而不是在写完之前读取整个文件,但它很麻烦而且有点棘手。基本上,您需要在读取和写入之间移动文件指针,并维护一个缓冲区,该缓冲区包含文件中的行,当写入每条修改的行时,这些行将被全部或部分覆盖。
在每个步骤中,从缓冲区中删除第一行并修改它以准备写入。但是,在写入之前,您可能需要将一个或多个附加行读入缓冲区,以便在写入修改行之后读指针保持在写指针之前。读完所有行后,缓冲区中的每个剩余行都被修改并写入。
<强>代码强>
def prepend_file_lines(file_name, text_to_prepend)
f = File.open(file_name, 'r+')
return if f.eof?
write_pos = 0
line_in = f.readline
read_pos = line_in.size
buf = [line_in]
last_line_read = f.eof?
loop do
break if buf.empty?
line_out = text_to_prepend + buf.shift
while (!last_line_read && read_pos <= write_pos + line_out.size) do
line_in = f.readline
buf << line_in
read_pos += line_in.size
last_line_read = f.eof?
end
f.seek(write_pos, IO::SEEK_SET)
write_pos += f.write(line_out)
f.seek(read_pos, IO::SEEK_SET)
end
end
示例强>
首先创建一个测试文件。
text =<<_
Now is
the time
for all Rubiests
to raise their
glasses to Matz.
_
F_NAME = "sample.txt"
File.write(F_NAME, text)
我们可以确认文件写得正确:
File.readlines(F_NAME).each { |l| puts l }
# Now is
# the time
# for all Rubiests
# to raise their
# glasses to Matz.
现在让我们试一试:
prepend_file_lines("sample.txt", "Here's to Matz: ")
File.readlines(F_NAME).each { |l| puts l }
# Here's to Matz: Now is
# Here's to Matz: the time
# Here's to Matz: for all Rubiests
# Here's to Matz: to raise their
# Here's to Matz: glasses to Matz.
请注意,在测试时,必须在每次调用prepend_file_lines
之前编写测试文件,因为文件正在被修改。
答案 1 :(得分:0)
您可以在同一个文件中执行此操作,但您可能会覆盖该文件的内容。
每个文件操作都将文件的光标设置到不同的位置,这是用于后面操作的位置。因此,如果您读取8个字节,则必须提前将光标返回8个字节并准确写入8个字节以不覆盖任何内容,如果写入更少的字节,则将保持不变的字节。
Ruby File类是IO类,在http://www.ruby-doc.org/core-1.9.3/IO.html中有记录。
要打开文件进行读/写操作,请使用“r +”模式。
答案 2 :(得分:0)
看起来你希望IO::SEEK_SET
和0
在阅读后回放文件指针。
file_name = "File.txt";
File.open(file_name , 'r+') do |f|
content = f.read
content.insert(0, "somehting else")
f.seek(0, IO::SEEK_SET)
f.write(content)
end