2011-06-17 34 views
0

我在一些将文件/ IO作为参数的ruby代码中使用了一个不透明的API。我希望能够传递一个IO对象,它只能访问实际IO对象中给定范围的数据。如何使用滑动窗口过滤器打包ruby 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项目看起来是最容易适应做到这一点,但似乎并没有直接支持这种使用情况。

回答

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摘要对象。

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

+0

我相信你在这里做的只是传递一个字符串(读取返回一个字符串/数据被分配给块,而不是IO类的一个实例),直到incr_digest,除非我失去了一些东西......? – wr0ngway 2011-06-17 17:43:48

+0

不,你是对的,这正是它所做的。我的错。但是,似乎你可以将它作为一个优化的工具来分块数据,然后将它作为IO对象发送给你的API ... 我正在寻找具有该功能的StringIO。 http://ruby-doc.org/stdlib/libdoc/stringio/rdoc/index.html – Ryanmt 2011-06-20 04:32:24

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 

并使用它,因为你会使用块变体。