Class: Net::SFTP::Operations::File

Inherits:
Object
  • Object
show all
Defined in:
lib/net/sftp/operations/file.rb

Overview

A wrapper around an SFTP file handle, that exposes an IO-like interface for interacting with the remote file. All operations are synchronous (blocking), making this a very convenient way to deal with remote files.

A wrapper is usually created via the Net::SFTP::Session#file factory:

file = sftp.file.open("/path/to/remote")
puts file.gets
file.close

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sftp, handle) ⇒ File

Creates a new wrapper that encapsulates the given handle (such as would be returned by Net::SFTP::Session#open!). The sftp parameter must be the same Net::SFTP::Session instance that opened the file.



27
28
29
30
31
32
33
34
# File 'lib/net/sftp/operations/file.rb', line 27

def initialize(sftp, handle)
  @sftp     = sftp
  @handle   = handle
  @pos      = 0
  @real_pos = 0
  @real_eof = false
  @buffer   = ""
end

Instance Attribute Details

#handleObject (readonly)

The SFTP file handle object that this object wraps



19
20
21
# File 'lib/net/sftp/operations/file.rb', line 19

def handle
  @handle
end

#posObject

The current position within the remote file



22
23
24
# File 'lib/net/sftp/operations/file.rb', line 22

def pos
  @pos
end

#sftpObject (readonly)

A reference to the Net::SFTP::Session instance that drives this wrapper



16
17
18
# File 'lib/net/sftp/operations/file.rb', line 16

def sftp
  @sftp
end

Instance Method Details

#closeObject

Closes the underlying file and sets the handle to nil. Subsequent operations on this object will fail.



46
47
48
49
# File 'lib/net/sftp/operations/file.rb', line 46

def close
  sftp.close!(handle)
  @handle = nil
end

#eof?Boolean

Returns true if the end of the file has been encountered by a previous read. Setting the current file position via #pos= will reset this flag (useful if the file’s contents have changed since the EOF was encountered).

Returns:

  • (Boolean)


55
56
57
# File 'lib/net/sftp/operations/file.rb', line 55

def eof?
  @real_eof && @buffer.empty?
end

#gets(sep_or_limit = $/, limit = Float::INFINITY) ⇒ Object

Reads up to the next instance of sep_string in the stream, and returns the bytes read (including sep_string). If sep_string is omitted, it defaults to $/. If EOF is encountered before any data could be read, #gets will return nil. If the first argument is an integer, or optional second argument is given, the returning string would not be longer than the given value in bytes.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/net/sftp/operations/file.rb', line 87

def gets(sep_or_limit=$/, limit=Float::INFINITY)
  if sep_or_limit.is_a? Integer
    sep_string = $/
    lim = sep_or_limit
  else
    sep_string = sep_or_limit
    lim = limit
  end

  delim = if sep_string && sep_string.length == 0
    "#{$/}#{$/}"
  else
    sep_string
  end

  loop do
    at = @buffer.index(delim) if delim
    if at
      offset = [at + delim.length, lim].min
      @pos += offset
      line, @buffer = @buffer[0,offset], @buffer[offset..-1]
      return line
    elsif lim < @buffer.length
      @pos += lim
      line, @buffer = @buffer[0,lim], @buffer[lim..-1]
      return line
    elsif !fill
      return nil if @buffer.empty?
      @pos += @buffer.length
      line, @buffer = @buffer, ""
      return line
    end
  end
end

Writes each argument to the stream. If $ is set, it will be written after all arguments have been written.



142
143
144
145
146
# File 'lib/net/sftp/operations/file.rb', line 142

def print(*items)
  items.each { |item| write(item) }
  write($\) if $\
  nil
end

#puts(*items) ⇒ Object

Writes each argument to the stream, appending a newline to any item that does not already end in a newline. Array arguments are flattened.



159
160
161
162
163
164
165
166
167
168
169
# File 'lib/net/sftp/operations/file.rb', line 159

def puts(*items)
  items.each do |item|
    if Array === item
      puts(*item)
    else
      write(item)
      write("\n") unless item[-1] == ?\n
    end
  end
  nil
end

#read(n = nil) ⇒ Object

Reads up to n bytes of data from the stream. Fewer bytes will be returned if EOF is encountered before the requested number of bytes could be read. Without an argument (or with a nil argument) all data to the end of the file will be read and returned.

This will advance the file pointer (#pos).



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/net/sftp/operations/file.rb', line 65

def read(n=nil)
  loop do
    break if n && @buffer.length >= n
    break unless fill
  end

  if n
    result, @buffer = @buffer[0,n], (@buffer[n..-1] || "")
  else
    result, @buffer = @buffer, ""
  end

  @pos += result.length
  return result
end

#readline(sep_or_limit = $/, limit = Float::INFINITY) ⇒ Object

Same as #gets, but raises EOFError if EOF is encountered before any data could be read.

Raises:

  • (EOFError)


124
125
126
127
128
# File 'lib/net/sftp/operations/file.rb', line 124

def readline(sep_or_limit=$/, limit=Float::INFINITY)
  line = gets(sep_or_limit, limit)
  raise EOFError if line.nil?
  return line
end

#rewindObject

Resets position to beginning of file



153
154
155
# File 'lib/net/sftp/operations/file.rb', line 153

def rewind
  self.pos = 0
end

#sizeObject



148
149
150
# File 'lib/net/sftp/operations/file.rb', line 148

def size
  stat.size
end

#statObject

Performs an fstat operation on the handle and returns the attribute object (Net::SFTP::Protocol::V01::Attributes, Net::SFTP::Protool::V04::Attributes, or Net::SFTP::Protocol::V06::Attributes, depending on the SFTP protocol version in use).



175
176
177
# File 'lib/net/sftp/operations/file.rb', line 175

def stat
  sftp.fstat!(handle)
end

#write(data) ⇒ Object

Writes the given data to the stream, incrementing the file position and returning the number of bytes written.



132
133
134
135
136
137
138
# File 'lib/net/sftp/operations/file.rb', line 132

def write(data)
  data = data.to_s
  sftp.write!(handle, @real_pos, data)
  @real_pos += data.bytes.length
  @pos = @real_pos
  data.bytes.length
end