ruby读取和写入/更改同一文件
我正在尝试更改现有文件的内容。我有这段代码,它是有效的。但我想找到一种更好的方法,在打开文件的一次操作中进行操作ruby读取和写入/更改同一文件,ruby,Ruby,我正在尝试更改现有文件的内容。我有这段代码,它是有效的。但我想找到一种更好的方法,在打开文件的一次操作中进行操作 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.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(文件名为'r+')
,它似乎只附加到文件的末尾(无法在文件的开头插入内容)。您可以在同一个文件中执行此操作,但可能会覆盖文件的内容
每个文件操作都会将文件的光标设置到不同的位置,这是后一个操作所使用的位置。所以,如果你读了8个字节,你必须提前8个字节返回光标,并且只写8个字节来不覆盖任何内容,如果你写的字节更少,你将保持不变的字节
Ruby文件类是IO类,在中有文档记录
要打开文件进行读/写操作,请使用“r+”模式。看起来您希望
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
[编辑:我误解了你的问题,但我下面的代码只需插入一行即可修复:
text_to_prepend = ''
之后
它可以简化一点(针对您的问题),但我将保持原样,以显示如何在每一行前面添加相同的字符串。]
您可以只打开一次文件,并且在写入之前不读取整个文件,但这很混乱,而且有点棘手。基本上,您需要在读取和写入之间移动文件指针,并维护一个缓冲区,该缓冲区包含文件中的行,当写入每个修改的行时,这些行将被全部或部分覆盖
在每个步骤中,从缓冲区中删除第一行并修改它以准备写入。但是,在写入之前,您可能需要将一个或多个附加行读入缓冲区,以便在写入修改后的行后,读取指针保持在写入指针之前。读取所有行后,修改并写入缓冲区中的每一行
代码
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
现在让我们试试:
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_line
之前写入测试文件,因为文件正在被修改。可以。如果不打开文件两次,我们怎么做?@dli只是使用“r+”模式。虽然这个问题乍一看并不是重复的,但我相信它问的问题与您的基本相同:如果文件非常大,这可能不是最好的主意-将整个原始文件读入内存不会有意思。@JKillian,这是非常正确的,但是由于OP提到他当前的解决方案已经开始工作,并且我没有改变内存要求,他没有处理足够大的文件来遇到这个问题。同意,小文件不应该是一个问题。只是为了将来读者的利益想提一下
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.