Ruby修改文件而不是创建新文件

时间:2016-09-02 05:08:52

标签: ruby file

假设我有以下Ruby代码,给定插入位置的哈希值,读取文件并创建一个新文件,并在这些位置插入额外的文本:

insertpos = {14=>25,16=>25}
File.open('file.old', 'r') do |oldfile|
    File.open('file.new', 'w') do |newfile|
        oldfile.each_with_index do |line,linenum|
            inserthere = insertpos[linenum]
            if(!inserthere.nil?)then
                line.insert(inserthere,"foo")
            end
            newfile.write(line)
        end
    end
end

现在,我想修改这个原始(旧)文件,而不是创建那个新文件。有人能给我一个如何修改代码的提示吗?谢谢!

3 个答案:

答案 0 :(得分:-1)

在一个非常基础的层面上,在任何语言中,在任何操作系统上这都是一件非常困难的事情。将一个文件设想为磁盘上连续的一系列字节(这是一个非常简单的场景,但它可以说明这一点)。您想在文件中间插入一些字节。你把这些字节放在哪里?没有地方可以放他们!在插入点“向下”之后,您必须基本上将现有字节“移位”您要插入的字节数。如果要在现有文件中插入多个部分,则必须多次执行此操作!这将非常缓慢,如果出现问题,您将面临破坏数据的高风险。

然而,可以覆盖现有字节,和/或附加到文件末尾。大多数Unix实用程序通过创建新文件并使用旧文件交换来呈现修改文件的外观。一些更复杂的方案,例如数据库使用的方案,允许在文件中间插入1.为这些操作保留空间(当数据首次写入时),2。通过索引允许文件中的非连续数据块和其他技术,和/或3.写时复制方案,其中将新版本的数据写入文件的末尾,并通过覆盖某种指示符使旧版本无效。您很可能不想为您的简单用例解决所有这些麻烦!

无论如何,你已经找到了做你想做的事情的最好方法。你唯一缺少的是最后用FileUtils.mv('file.new', 'file.old')来替换旧文件。如果我能帮助解释这一点,请在评论中告诉我。

(当然,您可以将整个文件读入内存,进行更改,并使用更新的内容覆盖旧文件,但我不相信这就是您在这里所要求的。)

答案 1 :(得分:-1)

这是希望能够解决你的目的的事情:

# 'source' param is a string, the entire source text
# 'lines' param is an array, a list of line numbers to insert after
# 'new' param is a string, the text to add
def insert(source, lines, new)
        results = []
        source.split("\n").each_with_index do |line, idx|
                if lines.include?(idx)
                        results << (line + new)
                else
                        results << line
                end
        end
        results.join("\n")
end

File.open("foo", "w") do |f|
        10.times do |i|
                f.write("#{i}\n")
        end
end

puts "initial text: \n\n"
txt = File.read("foo")
puts txt

puts "\n\n after inserting at lines 1,3, and 5: \n\n"
result = insert(txt, [1,3,5], "\nfoo")
puts result

运行此显示:

initial text: 

0
1
2
3
4
5
6
7
8
9


 after inserting at lines 1,3, and 5: 

0
1
foo
2
3
foo
4
5
foo
6
7
8

答案 2 :(得分:-1)

如果它是一个相对简单的操作,你可以使用红宝石单行,如此

ruby -i -lpe '$_.reverse!' thefile.txt

(例如在https://gist.github.com/KL-7/1590797处找到。)