Как обернуть ruby ​​IO фильтром скользящего окна - PullRequest
0 голосов
/ 17 июня 2011

Я использую непрозрачный API в некотором коде ruby, который принимает File / IO в качестве параметра.Я хочу иметь возможность передать ему объект ввода-вывода, который дает доступ только к определенному диапазону данных в реальном объекте ввода-вывода.

Например, у меня есть файл 8 ГБ, и я хочу дать APIОбъект ввода-вывода, имеющий диапазон 1 ГБ в середине моего реального файла.

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 ]

1 голос
/ 17 июня 2011

Я думаю, что вам придется написать это самостоятельно, поскольку это кажется довольно специфической вещью: вам придется реализовать все (или нужное подмножество) из 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.

0 голосов
/ 17 июня 2011

Я считаю, что объект ввода-вывода обладает той функциональностью, которую вы ищете.Я использовал его ранее для суммирования 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 / ядро ​​/ классов / IO.html # M000918

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...