Ruby 将打开文件,但不会写入文件



我正在尝试创建一个基本的红宝石抓取器,它将从 html 源代码中抓取所有 8 个字母或更长的单词。 然后,它将这些保存在与单词的第一个字符相对应的文件中。 看起来很简单吧?

    re = /w{8,}/
    cre = /[a-z0-9]/
    a = b.html    #This grabs the html from the browser
    matchx = a.scan(re)
    matchx.each do |xx|
        word = xx.to_s.downcase.chomp
        fchar = word[0].chr
        if (fchar.match(cre)) #Not sure if I need this
            @pcount += 1
            fname = @WordsFName+fchar   #@WordsFName is a prefix
            tmpF = File.open(fname,"a+")
            #Check for duplicates, if not write to file
            exists = File.readlines(fname).any? { |li| li[word] }
            if (!exists)                    
                tmpF.write(word+"n")
                print word 
                @wcount += 1
            end
        end
    end

Ruby 成功抓取了所有单词,获取了第一个字符,并打开了所有必要的文件,但无法写入。 此外,打印方法打印所有单词,包括重复项,但检查任何?IRB的方法没有问题。.

File#write 是缓冲的,你不会在写入和 File.readlines(fname) 之间刷新或关闭 tmpF,因此在刷新之前,读取行永远不会看到输出。我没有看到任何关闭 tmpF 的调用,因此,除了文件对象最终确定时的程序退出或 tmpF 超出范围后的一段时间后 GC 之外,不清楚何时刷新写入数据。

您可以使用 tmpF.flush 在写入后手动刷新,或者在打开后使用 tmpF.sync = true 进行默认行为。

请注意,随着每个文件变大,当它重新读取整个文件时,dup检查的成本将会膨胀。 如果单词集适合内存,请考虑只保留您见过的单词的哈希值,如果它大于可以存储在内存中的哈希值,请考虑键值存储,而不是每次都重新读取串行文件。

我在 irb 中玩了一圈以了解刷新行为。OP 代码的主要问题是 tmpF 文件上没有显式/隐式刷新或关闭。因此,可能小于缓冲区大小的部分写入仅在 tmpF File 对象被垃圾回收或程序退出时写入。tmpF 每次通过循环都会被分配一个新打开的文件对象,因此在以前的迭代中打开的文件只有在 GC 上完成时才会被刷新。

irb(main):001:0> t=File.open('zzz','a+')
=> #<File:zzz>
irb(main):002:0> t.write '123'
=> 3
irb(main):003:0> File.readlines('zzz')
=> []
irb(main):004:0> t=File.open('zzz','a+')
=> #<File:zzz>
irb(main):005:0> t.write '456'
=> 3
irb(main):006:0> File.readlines('zzz')
=> []
irb(main):007:0> t.close
=> nil
irb(main):008:0> File.readlines('zzz')
=> ["456"]
irb(main):009:0> t=File.open('zzz','a+')
=> #<File:zzz>
irb(main):010:0> t.write '789'
=> 3
irb(main):011:0> File.readlines('zzz')
=> ["456"]
irb(main):012:0> t.flush
=> #<File:zzz>
irb(main):013:0> File.readlines('zzz')
=> ["456789"]
irb(main):014:0> GC.start
=> nil
irb(main):015:0> File.readlines('zzz')
=> ["456789123"]

最新更新