Class: EM::File
- Inherits:
-
Object
- Object
- EM::File
- Defined in:
- lib/em-files.rb
Overview
Sequenced file reader and writer.
Constant Summary collapse
- RWSIZE =
Holds the default size of block operated during one tick.
65536
Instance Attribute Summary collapse
-
#mode ⇒ String
readonly
Holds mode of the object.
-
#native ⇒ IO
Holds file object.
-
#rw_len ⇒ Integer
Indicates block size for operate with in one tick.
Class Method Summary collapse
-
.open(filepath, mode = "r", rwsize = self::RWSIZE, &block) ⇒ File
Opens the file.
- .read(filepath, rwsize = self::RWSIZE, filter = nil, &block) ⇒ Object
-
.write(filepath, data = "", rwsize = self::RWSIZE, filter = nil, &block) ⇒ Object
Writes data to file and closes it.
Instance Method Summary collapse
-
#close ⇒ Object
Closes the file.
-
#initialize(filepath, mode = "r", rwsize = self.class::RWSIZE) ⇒ File
constructor
Constructor.
-
#read(length = nil, filter = nil, &block) ⇒ Object
Reads data from file.
-
#reopen! ⇒ Object
Reopens the file with the original mode.
-
#write(data, filter = nil, &block) ⇒ Object
Writes data to file.
Constructor Details
#initialize(filepath, mode = "r", rwsize = self.class::RWSIZE) ⇒ File
Constructor. If IO object is given instead of filepath, uses it as native one and mode argument is ignored.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/em-files.rb', line 135 def initialize(filepath, mode = "r", rwsize = self.class::RWSIZE) @mode = mode @rw_len = rwsize rwsize = self::RWSIZE if rwsize.nil? # If filepath is directly IO, uses it if filepath.kind_of_any? [StringIO, IO] @native = filepath else @native = ::File::open(filepath, mode) end end |
Instance Attribute Details
#mode ⇒ String (readonly)
Holds mode of the object.
123 124 125 |
# File 'lib/em-files.rb', line 123 def mode @mode end |
#native ⇒ IO
Holds file object.
107 108 109 |
# File 'lib/em-files.rb', line 107 def native @native end |
#rw_len ⇒ Integer
Indicates block size for operate with in one tick.
115 116 117 |
# File 'lib/em-files.rb', line 115 def rw_len @rw_len end |
Class Method Details
.open(filepath, mode = "r", rwsize = self::RWSIZE, &block) ⇒ File
Opens the file.
In opposite to appropriate Ruby method, “block syntax” is only syntactic sugar, file isn’t closed after return from block because processing is asynchronous so it doesn’t know when is convenient to close the file.
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/em-files.rb', line 42 def self.open(filepath, mode = "r", rwsize = self::RWSIZE, &block) # 64 kilobytes rwsize = self::RWSIZE if rwsize.nil? file = self::new(filepath, mode, rwsize) if not block.nil? block.call(file) end return file end |
.read(filepath, rwsize = self::RWSIZE, filter = nil, &block) ⇒ Object
66 67 68 69 70 71 72 73 74 |
# File 'lib/em-files.rb', line 66 def self.read(filepath, rwsize = self::RWSIZE, filter = nil, &block) rwsize = self::RWSIZE if rwsize.nil? self::open(filepath, "rb", rwsize) do |io| io.read(nil, filter) do |out| io.close() block.call(out) end end end |
.write(filepath, data = "", rwsize = self::RWSIZE, filter = nil, &block) ⇒ Object
Writes data to file and closes it. Writes them in binary mode. If IO object is given instead of filepath, uses it as native one and mode argument is ignored.
90 91 92 93 94 95 96 97 98 |
# File 'lib/em-files.rb', line 90 def self.write(filepath, data = "", rwsize = self::RWSIZE, filter = nil, &block) rwsize = self::RWSIZE if rwsize.nil? self::open(filepath, "wb", rwsize) do |io| io.write(data, filter) do |length| io.close() block.call(length) end end end |
Instance Method Details
#close ⇒ Object
Closes the file.
287 288 289 |
# File 'lib/em-files.rb', line 287 def close @native.close end |
#read(length, &block) ⇒ Object #read(&block) ⇒ Object
Reads data from file.
It will reopen the file if EBADF: Bad file descriptor of File class IO object will occur.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/em-files.rb', line 168 def read(length = nil, filter = nil, &block) buffer = "" pos = 0 # Arguments if length.kind_of? Proc filter = length end worker = Proc::new do # Sets length for read if not length.nil? rlen = length - buffer.length if rlen > @rw_len rlen = @rw_len end else rlen = @rw_len end # Reads begin chunk = @native.read(rlen) if not filter.nil? chunk = filter.call(chunk) end buffer << chunk rescue Errno::EBADF if @native.kind_of? ::File self.reopen! @native.seek(pos) redo else raise end end pos = @native.pos # Returns or continues work if @native.eof? or (buffer.length == length) if not block.nil? block.call(buffer) # returns result end else EM::next_tick { worker.call() } # continues work end end worker.call() end |
#reopen! ⇒ Object
Reopens the file with the original mode.
227 228 229 |
# File 'lib/em-files.rb', line 227 def reopen! @native = ::File.open(@native.path, @mode) end |
#write(data, filter = nil, &block) ⇒ Object
Writes data to file.
It will reopen the file if EBADF: Bad file descriptor of File class IO object will occur.
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/em-files.rb', line 244 def write(data, filter = nil, &block) written = 0 pos = 0 worker = Proc::new do # Writes begin chunk = data[written...(written + @rw_len)] if not filter.nil? chunk = filter.call(chunk) end written += @native.write(chunk) rescue Errno::EBADF if @native.kind_of? File self.reopen! @native.seek(pos) redo else raise end end pos = @native.pos # Returns or continues work if written >= data.bytesize if not block.nil? block.call(written) # returns result end else EM::next_tick { worker.call() } # continues work end end worker.call() end |