Spec-Zone.ru › Ruby 3.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 или закрытие в блоке ensure, как показано ниже:

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

Tempfile.create { … } создан для этой цели и удобнее в использовании. Обратите внимание, что Tempfile.create возвращает экземпляр File вместо Tempfile, что также позволяет избежать накладных расходов и сложностей делегирования.

Tempfile.open('foo') do |file|
   # ...do something with file...
end

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

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

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

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

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

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

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

Общедоступные методы класса

create(basename="", tmpdir=nil, mode: 0, **options) { |tmpfile| ... } Показать исходный код
# File lib/tempfile.rb, line 398
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
      unless tmpfile.closed?
        if File.identical?(tmpfile, tmpfile.path)
          unlinked = File.unlink tmpfile.path rescue nil
        end
        tmpfile.close
      end
      unless unlinked
        begin
          File.unlink tmpfile.path
        rescue Errno::ENOENT
        end
      end
    end
  else
    tmpfile
  end
end

Создает файл в файловой системе; возвращает новый объект File, основанный на этом файле.

Без блока и без аргументов создает и возвращает файл, чьи:

  • Class является File (не Tempfile).

  • Директория — это системная временная директория (зависит от системы).

  • Сгенерированное имя файла уникально в этой директории.

  • Разрешения — 0600; см. Разрешения файлов.

  • Режим — 'w+' (режим чтения/записи, позиция в конце).

Без блока файл не удаляется автоматически и поэтому должен быть удален явно.

Пример:

f = Tempfile.create     # => #<File:/tmp/20220505-9795-17ky6f6>
f.class                 # => File
f.path                  # => "/tmp/20220505-9795-17ky6f6"
f.stat.mode.to_s(8)     # => "100600"
File.exist?(f.path)     # => true
File.unlink(f.path)
File.exist?(f.path)     # => false

Аргумент basename, если указан, может быть одним из:

  • Строка: сгенерированное имя файла начинается с basename:

    Tempfile.create('foo') # => #<File:/tmp/foo20220505-9795-1gok8l9>
    
  • Массив из двух строк [prefix, suffix]: сгенерированное имя файла начинается с prefix и заканчивается suffix:

    Tempfile.create(%w/foo .jpg/) # => #<File:/tmp/foo20220505-17839-tnjchh.jpg>
    

С аргументами basename и tmpdir, файл создается в директории tmpdir:

Tempfile.create('foo', '.') # => #<File:./foo20220505-9795-1emu6g8>

Ключевые аргументы mode и options передаются напрямую методу File.open:

  • Значение, заданное с помощью mode должно быть целым числом и может быть выражено как логическое ИЛИ констант, определенных в File::Constants.

  • Для options, см. Параметры открытия.

С заданным блоком, создает файл как указано выше, передает его в блок и возвращает значение блока; перед возвратом объект файла закрывается, а базовый файл удаляется:

Tempfile.create {|file| file.path } # => "/tmp/20220505-9795-rkists"

Связанное: Tempfile.new.

new(basename="", tmpdir=nil, mode: 0, **options) Показать исходный код
# File lib/tempfile.rb, line 148
def initialize(basename="", tmpdir=nil, mode: 0, **options)
  warn "Tempfile.new doesn't call the given block.", uplevel: 1 if block_given?

  @unlinked = false
  @mode = mode|File::RDWR|File::CREAT|File::EXCL
  ::Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
    opts[:perm] = 0600
    @tmpfile = File.open(tmpname, @mode, **opts)
    @opts = opts.freeze
  end
  ObjectSpace.define_finalizer(self, Remover.new(@tmpfile))

  super(@tmpfile)
end

Создает файл в файловой системе; возвращает новый объект Tempfile, основанный на этом файле.

Если возможно, используйте вместо этого Tempfile.create, который:

  • Избегает накладных расходов на делегирование, возникающих, когда Tempfile.new вызывает свой суперкласс DelegateClass(File).

  • Не полагается на финализатор для закрытия и удаления файла, что может быть ненадежным.

Создает и возвращает файл, чьи:

  • Class является Tempfile (не File, как в Tempfile.create).

  • Директория — это системная временная директория (зависит от системы).

  • Сгенерированное имя файла уникально в этой директории.

  • Разрешения — 0600; см. Разрешения файлов.

  • Режим — 'w+' (режим чтения/записи, позиция в конце).

Базовый файл удаляется, когда объект Tempfile умирает и забирается сборщиком мусора.

Пример:

f = Tempfile.new # => #<Tempfile:/tmp/20220505-17839-1s0kt30>
f.class               # => Tempfile
f.path                # => "/tmp/20220505-17839-1s0kt30"
f.stat.mode.to_s(8)   # => "100600"
File.exist?(f.path)   # => true
File.unlink(f.path)   #
File.exist?(f.path)   # => false

Аргумент basename, если указан, может быть одним из:

  • Строка: сгенерированное имя файла начинается с basename:

    Tempfile.new('foo') # => #<Tempfile:/tmp/foo20220505-17839-1whk2f>
    
  • Массив из двух строк [prefix, suffix]: сгенерированное имя файла начинается с prefix и заканчивается suffix:

    Tempfile.new(%w/foo .jpg/) # => #<Tempfile:/tmp/foo20220505-17839-58xtfi.jpg>
    

С аргументами basename и tmpdir, файл создается в директории tmpdir:

Tempfile.new('foo', '.') # => #<Tempfile:./foo20220505-17839-xfstr8>

Ключевые аргументы mode и options передаются напрямую методу File.open:

  • Значение, заданное с помощью mode должно быть целым числом и может быть выражено как логическое ИЛИ констант, определенных в File::Constants.

  • Для options, см. Параметры открытия.

Связанное: Tempfile.create.

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

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

Создает новый Tempfile.

Этот метод не рекомендуется и существует в основном для обратной совместимости. Пожалуйста, используйте Tempfile.create вместо него, что позволяет избежать затрат на делегирование, не полагается на финализатор и также удаляет файл при использовании блока.

Tempfile.open все еще подходит, если вам нужен Tempfile для удаления финализатором, и вы не можете явно указать, где в программе Tempfile можно безопасно удалить.

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

Если задан блок, то будет создан объект Tempfile, и блок будет выполнен с объектом Tempfile в качестве аргумента. Объект Tempfile будет автоматически закрыт после завершения блока. Однако файл не будет удален и необходимо вручную удалить его с помощью Tempfile#close! или Tempfile#unlink. Финализатор попытается удалить файл, но на него нельзя полагаться, так как он может сохранить файл на диске гораздо дольше, чем предполагалось. Например, в CRuby финализаторы могут быть отложены из-за консервативного сканирования стека и ссылок, оставленных в неиспользуемой памяти.

Вызов возвращает значение блока.

В любом случае, все аргументы (*args) будут переданы в Tempfile.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 182
def close(unlink_now=false)
  _close
  unlink if unlink_now
end

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

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

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

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

delete()
Псевдоним для: unlink
length()
Псевдоним для: size
open() Показать исходный код
# File lib/tempfile.rb, line 164
def open
  _close
  mode = @mode & ~(File::CREAT|File::EXCL)
  @tmpfile = File.open(@tmpfile.path, mode, **@opts)
  __setobj__(@tmpfile)
end

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

path() Показать исходный код
# File lib/tempfile.rb, line 242
def path
  @unlinked ? nil : @tmpfile.path
end

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

size() Показать исходный код
# File lib/tempfile.rb, line 248
def size
  if !@tmpfile.closed?
    @tmpfile.size # File#size calls rb_io_flush_raw()
  else
    File.size(@tmpfile.path)
  end
end

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

Также алиас для: length
unlink() Показать исходный код
# File lib/tempfile.rb, line 226
def unlink
  return if @unlinked
  begin
    File.unlink(@tmpfile.path)
  rescue Errno::ENOENT
  rescue Errno::EACCES
    # may not be able to unlink on Windows; just ignore
    return
  end
  ObjectSpace.undefine_finalizer(self)
  @unlinked = true
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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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