如何使用滑动窗口过滤器包装ruby IO

时间:2011-06-17 13:39:41

标签: ruby io

我在一些ruby代码中使用了一个不透明的API,它以File / IO作为参数。我希望能够传递一个IO对象,该对象只能访问真实IO对象中给定范围的数据。

例如,我有一个8GB的文件,我想给api一个在我的真实文件中间有1GB范围的IO对象。

real_file = File.new('my-big-file')
offset = 1 * 2**30 # start 1 GB into it
length = 1 * 2**30 # end 1 GB after start
filter = IOFilter.new(real_file, offset, length)

# The api only sees the 1GB of data in the middle
opaque_api(filter)

filter_io项目看起来最容易适应这一点,但似乎并不直接支持这个用例。

2 个答案:

答案 0 :(得分:1)

我认为你必须自己编写,因为它似乎是一个相当具体的事情:你必须使用一大块来实现IO方法的所有(或者你需要的子集)打开的文件作为数据源。 “专业”的一个例子是写入这样的流 - 你必须注意不要跨越给定段的边界,即不断跟踪你在大文件中的当前位置。看起来不是一件微不足道的工作,而且我没有看到任何可以帮助你的捷径。

也许您可以找到一些基于操作系统的解决方案,例如将环回设备从大文件的部分中取出(例如,请参阅man losetup,尤其是-o--sizelimit选项。

变式2:

如果您可以随时将窗口内容保存在内存中,可以像这样包装StringIO(只是草图,未经测试):

def sliding_io filename, offset, length
  File.open(filename, 'r+') do |f|
    # read the window into a buffer
    f.seek(offset)
    buf = f.read(length)
    # wrap a buffer into StringIO and pass it given block
    StringIO.open(buf) do |buf_io|
      yield(buf_io)
    end
    # write altered buffer back to the big file
    f.seek(offset)
    f.write(buf[0,length])
  end
end

并使用它,就像使用IO#open的块变体一样。

答案 1 :(得分:0)

我相信IO对象具有您正在寻找的功能。我之前使用过MD5哈希求和类似大小的文件。

incr_digest = Digest::MD5.new()
file = File.open(filename, 'rb') do |io|
    while chunk = io.read(50000)
        incr_digest << chunk
    end
end

这是我使用的块,我将块传递给MD5 Digest对象。

http://www.ruby-doc.org/core/classes/IO.html#M000918