ruby读取和写入/更改相同的文件

时间:2014-07-23 00:23:16

标签: 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_name , 'r+'),它似乎只附加到文件的末尾(无法在文件的开头插入内容)。

3 个答案:

答案 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_SET0在阅读后回放文件指针。

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