Spec-Zone.ru › Ruby 2.2

класс Tempfile

Родитель:
DelegateClass(File)

Утилитарный класс для управления временными файлами. При создании объекта Tempfile, он создаст временный файл с уникальным именем. Объект Tempfile ведет себя как объект File, и вы можете выполнять все обычные операции с файлами: чтение данных, запись данных, изменение разрешений и т.д. Хотя этот класс не документирует все методы экземпляров, поддерживаемые File, вы можете использовать любой метод экземпляра File с объектом Tempfile.

Синопсис

require 'tempfile'

file = Tempfile.new('foo')
file.path      # => A unique filename in the OS's temp directory,
               #    e.g.: "/tmp/foo.24722.0"
               #    This filename contains 'foo' in its basename.
file.write("hello world")
file.rewind
file.read      # => "hello world"
file.close
file.unlink    # deletes the temp file

Рекомендации по использованию

Явное закрытие

Когда объект Tempfile удаляется сборщиком мусора или когда интерпретатор Ruby завершается, связанный с ним временный файл автоматически удаляется. Это означает, что нет необходимости явно удалять Tempfile после использования, хотя это хорошая практика: неявное удаление неиспользуемых Tempfile может привести к накоплению временных файлов в файловой системе до их удаления сборщиком мусора. Наличие этих временных файлов может затруднить определение нового имени файла Tempfile.

Поэтому всегда следует вызывать unlink или close в блоке ensure, например:

file = Tempfile.new('foo')
begin
   ...do something with file...
ensure
   file.close
   file.unlink   # deletes the temp file
end

Удаление после создания

В системах POSIX возможно удалить файл сразу после его создания и перед закрытием. Это удаляет запись в файловой системе без закрытия дескриптора файла, что гарантирует, что только процессы, которые уже открыли дескриптор файла, могут получить доступ к его содержимому. Настоятельно рекомендуется сделать это, если вы не хотите, чтобы другие процессы могли читать или записывать в Tempfile, и вам также не нужно знать имя Tempfile.

Например, практическое применение удаления после создания может быть таким: вам нужен большой буфер байтов, который слишком велик для комфортного размещения в оперативной памяти, например, при написании веб-сервера и при буферизации данных загружаемого клиентом файла.

Дополнительную информацию и пример кода см. в unlink.

Дополнительные заметки

Метод выбора имени файла для Tempfile является потокобезопасным и безопасным для межпроцессного взаимодействия: он гарантирует, что никакие другие потоки или процессы не выберут то же имя файла.

Однако сам Tempfile может не быть полностью потокобезопасным. Если вы обращаетесь к одному и тому же объекту Tempfile из нескольких потоков, то вы должны защитить его с помощью мьютекса.

Методы публичного класса

create(basename, tmpdir=nil, mode: 0, **options) { |tmpfile| ... } Показать исходный код
# File lib/tempfile.rb, line 350
def Tempfile.create(basename, tmpdir=nil, mode: 0, **options)
  tmpfile = nil
  Dir::Tmpname.create(basename, tmpdir, options) do |tmpname, n, opts|
    mode |= File::RDWR|File::CREAT|File::EXCL
    opts[:perm] = 0600
    tmpfile = File.open(tmpname, mode, opts)
  end
  if block_given?
    begin
      yield tmpfile
    ensure
      tmpfile.close if !tmpfile.closed?
      File.unlink tmpfile
    end
  else
    tmpfile
  end
end

Создаёт временный файл как обычный объект File (а не Tempfile). Не использует финализаторы и делегирование.

Если блок не задан, это аналогично ::new, за исключением того, что создаётся объект File, а не Tempfile. Созданный файл не удаляется автоматически. Для его удаления используйте File.unlink.

Если блок задан, то будет создан объект File, и блок будет вызван с объектом в качестве аргумента. Объект File будет автоматически закрыт, а временный файл удалён после завершения блока. Вызов возвращает значение блока.

В любом случае, все аргументы (+*args+) будут обработаны так же, как в ::new.

Tempfile.create('foo', '/home/temp') do |f|
   ... do something with f ...
end
new(basename, [tmpdir = Dir.tmpdir], [options]) Показать исходный код
# File lib/tempfile.rb, line 125
def initialize(basename, tmpdir=nil, mode: 0, **options)
  if block_given?
    warn "Tempfile.new doesn't call the given block."
  end
  @data = []
  @clean_proc = Remover.new(@data)
  ObjectSpace.define_finalizer(self, @clean_proc)

  ::Dir::Tmpname.create(basename, tmpdir, options) do |tmpname, n, opts|
    mode |= File::RDWR|File::CREAT|File::EXCL
    opts[:perm] = 0600
    @data[1] = @tmpfile = File.open(tmpname, mode, opts)
    @data[0] = @tmpname = tmpname
    @mode = mode & ~(File::CREAT|File::EXCL)
    opts.freeze
    @opts = opts
  end

  super(@tmpfile)
end

Создаёт временный файл с разрешениями 0600 (= доступен только для чтения и записи владельцу) и открывает его в режиме “w+”.

Параметр basename используется для определения имени временного файла. Вы можете передать строку или массив из 2 строк. В первом случае, имя временного файла будет начинаться с переданной строки. Во втором случае, имя временного файла будет начинаться с первого элемента массива и заканчиваться вторым. Например:

file = Tempfile.new('hello')
file.path  # => something like: "/tmp/hello2843-8392-92849382--0"

# Use the Array form to enforce an extension in the filename:
file = Tempfile.new(['hello', '.jpg'])
file.path  # => something like: "/tmp/hello2843-8392-92849382--0.jpg"

Временный файл будет помещён в директорию, указанную параметром tmpdir. По умолчанию это Dir.tmpdir. Если $SAFE > 0 и переданный tmpdir является загрязнённым, в качестве временного каталога используется '/tmp'. Обратите внимание, что значения ENV по умолчанию загрязнены, а возвращаемое значение Dir.tmpdir может быть получено из переменных окружения (например, $TMPDIR).

file = Tempfile.new('hello', '/home/aisaka')
file.path  # => something like: "/home/aisaka/hello2843-8392-92849382--0"

Также можно передать хэш опций. Внутри Tempfile создаёт временный файл с использованием File.open. Эти опции будут переданы в File.open. Это в основном полезно для указания опций кодирования, например:

Tempfile.new('hello', '/home/aisaka', :encoding => 'ascii-8bit')

# You can also omit the 'tmpdir' parameter:
Tempfile.new('hello', :encoding => 'ascii-8bit')

Исключения

Если ::new не может найти уникальное имя файла за ограниченное число попыток, то он генерирует исключение.

Вызывает метод суперкласса
open(*args) { |tempfile| ... } Показать исходный код
# File lib/tempfile.rb, line 314
def open(*args)
  tempfile = new(*args)

  if block_given?
    begin
      yield(tempfile)
    ensure
      tempfile.close
    end
  else
    tempfile
  end
end

Создаёт новый объект Tempfile.

Если блок не задан, это синоним для ::new.

Если блок задан, то будет создан объект Tempfile, и блок будет выполнен с этим объектом в качестве аргумента. Объект Tempfile будет автоматически закрыт после завершения блока. Вызов возвращает значение блока.

В любом случае, все аргументы (+*args+) будут переданы в ::new.

Tempfile.open('foo', '/home/temp') do |f|
   ... do something with f ...
end

# Equivalent:
f = Tempfile.open('foo', '/home/temp')
begin
   ... do something with f ...
ensure
   f.close
end

Методы публичного экземпляра

close(unlink_now=false) Показать исходный код
# File lib/tempfile.rb, line 170
def close(unlink_now=false)
  if unlink_now
    close!
  else
    _close
  end
end

Закрывает файл. Если unlink_now равно true, файл будет удалён после закрытия. Конечно, вы можете позже вызвать unlink, если не удаляете его сейчас.

Если вы не удаляете временный файл явно, удаление будет отложено до финализации объекта.

close!() Показать исходный код
# File lib/tempfile.rb, line 180
def close!
  _close
  unlink
end

Закрывает и удаляет файл. Имеет тот же эффект, что и вызов close(true).

delete()
Псевдоним для: unlink
length()
Псевдоним для: size
open() Показать исходный код
# File lib/tempfile.rb, line 147
def open
  @tmpfile.close if @tmpfile
  @tmpfile = File.open(@tmpname, @mode, @opts)
  @data[1] = @tmpfile
  __setobj__(@tmpfile)
end

Открывает или повторно открывает файл в режиме “r+”.

path() Показать исходный код
# File lib/tempfile.rb, line 236
def path
  @tmpname
end

Возвращает полное имя временного файла. Будет равно nil, если unlink был вызван.

size() Показать исходный код
# File lib/tempfile.rb, line 242
def size
  if @tmpfile
    @tmpfile.flush
    @tmpfile.stat.size
  elsif @tmpname
    File.size(@tmpname)
  else
    0
  end
end

Возвращает размер временного файла. В качестве побочного эффекта, буфер IO сбрасывается перед определением размера.

Также алиасируется как: length
unlink() Показать исходный код
# File lib/tempfile.rb, line 218
def unlink
  return unless @tmpname
  begin
    File.unlink(@tmpname)
  rescue Errno::ENOENT
  rescue Errno::EACCES
    # may not be able to unlink on Windows; just ignore
    return
  end
  # remove tmpname from remover
  @data[0] = @data[1] = nil
  @tmpname = nil
  ObjectSpace.undefine_finalizer(self)
end

Удаляет файл из файловой системы. Всегда удаляйте файл после использования, как описано в разделе «Явное закрытие» в обзоре Tempfile:

file = Tempfile.new('foo')
begin
   ...do something with file...
ensure
   file.close
   file.unlink   # deletes the temp file
end

Удаление перед закрытием

В системах POSIX можно удалить файл до его закрытия. Этот приём подробно описан в обзоре Tempfile (раздел «Удаление после создания»); для получения дополнительной информации обратитесь туда.

Однако, удаление перед закрытием может быть не поддерживается в не-POSIX операционных системах. Microsoft Windows — наиболее заметный случай: удаление не закрытого файла приведёт к ошибке, которая этим методом будет проигнорирована. Если вы хотите использовать удаление перед закрытием, когда это возможно, следует писать код так:

file = Tempfile.new('foo')
file.unlink   # On Windows this silently fails.
begin
   ... do something with file ...
ensure
   file.close!   # Closes the file handle. If the file wasn't unlinked
                 # because #unlink failed, then this method will attempt
                 # to do so again.
end
Также алиасируется как: delete

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API