2011-06-17 15 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 

並使用它,因爲你會使用塊變體。