Return to Snippet

Revision: 5834
at April 7, 2008 07:17 by neil


Initial Code
require 'initialized_by_hash'


# copies a file, providing feedback on the progress of the operation.
#
#  source:       a path to the file that should be duplicated
#  destination:  a path to the the new copy
#  report_rate:  the number of times each second to report
#
# example:
#   fd = FileDuplication.new :source => ARGV[0], :destination => ARGV[1]
#   fd.begin do | bytes_done, bytes_left|
#     puts '%i %i' % [ bytes_done, bytes_left]
#   end
#
class FileDuplication

  attr_accessor :source, :destination, :report_rate

  initialized_by_hash


 private

  def fill_in_blanks
    @report_rate = 10 unless @report_rate
  end


 public

  # begins this file duplication operation, providing feedback to the default
  # block as the operation progresses.
  #
  def begin
    # check that both source and destination have been specified
    raise 'cannot copy from an unspecified source' unless @source
    raise 'cannot copy to unspecified destination' unless @destination

    begin
      source = File.open @source
      sink   = File.open @destination, 'w'

      bytes_done         = 0
      bytes_left         = File.size @source
      when_last_reported = Time.at 0
      scrap              = ''

      # report the commencement of the operation
      yield  bytes_done, bytes_left

      # while there are still some bytes left to copy..
      while 0 < bytes_left do

        # don't try to copy more bytes than are left to copy
        block_size = [ 10240, bytes_left].min

        # copy the bytes in the focus block
        source.sysread block_size, scrap
        sink.syswrite scrap

        bytes_done += block_size
        bytes_left -= block_size

        # if enough time has passed that another report should be made..
        now = Time.now
        if when_last_reported + 1.0 / @report_rate <= now

          # report on progress
          yield  bytes_done, bytes_left

          when_last_reported = now
        end
      end

      # report the completion of the operation
      yield  bytes_done, bytes_left

    ensure

      sink.close if sink
      source.close if source
    end
  end

end

# --------------------------------------------------------------- 80 column rule

Initial URL


Initial Description


Initial Title
file_duplication

Initial Tags
file, ruby, copy

Initial Language
Ruby