【问题标题】:How to get a filename from an IO object in ruby如何从 Ruby 中的 IO 对象获取文件名
【发布时间】:2011-12-14 20:03:29
【问题描述】:

在红宝石中...

我有一个由外部进程创建的 IO 对象,我需要从中获取文件名。 但是我似乎只能获取文件描述符(3),这对我来说不是很有用。

有没有办法从这个对象中获取文件名,甚至获取一个文件对象?

我正在从通知程序获取 IO 对象。那么这可能也是获取文件路径的一种方式吗?

【问题讨论】:

    标签: ruby io


    【解决方案1】:

    how to get a the filename in C上也有类似的问题,我这里用红宝石的方式给出这个问题的答案。

    在 Linux 中获取文件名

    假设 io 是您的 IO 对象。以下代码为您提供文件名。

    File.readlink("/proc/self/fd/#{io.fileno}")
    

    这不起作用,例如,如果在为其创建 io 对象后删除了文件。使用此解决方案,您有文件名,但没有 File 对象。

    获取一个不知道文件名的 File 对象

    IO#for_fd 方法可以创建一个 IO,它是任何给定整数文件描述符的子类。您可以通过以下方式为您的 fd 获取 File 对象:

    File.for_fd(io.fileno)
    

    不幸的是,这个 File 对象不知道文件名。

    File.for_fd(io.fileno).path # => nil
    

    我浏览了 ruby​​-1.9.2 源代码。在创建文件对象后,纯 ruby​​ 似乎无法操作路径。

    获取一个知道文件名的 File 对象

    可以在 C 中创建对 ruby​​ 的扩展,它首先调用 File#for_fd,然后操作文件内部数据结构。此源代码适用于 ruby​​-1.9.2,对于其他版本的 ruby​​,它可能需要进行调整。

    #include "ruby.h"
    #include "ruby/io.h"
    
    VALUE file_fd_filename(VALUE self, VALUE fd, VALUE filename) {
        VALUE file= rb_funcall3(self, rb_intern("for_fd"), 1, &fd);
        rb_io_t *fptr= RFILE(rb_io_taint_check(file))->fptr;
        fptr->pathv= rb_str_dup(filename);
        return file;
    }
    
    void Init_filename() {
    
        rb_define_singleton_method(rb_cFile, "for_fd_with_filename", file_fd_filename, 2);
    
    }
    

    现在你可以在编译后做:

    require "./filename"
    f= File.for_fd_with_filename(io.fileno, File.readlink("/proc/self/fd/#{io.fileno}"))
    f.path # => the filename
    

    也可以将读取链接放入File#for_fd_with_filename 定义中。这个例子只是为了展示它是如何工作的。

    【讨论】:

    • 不会在 BSD 上运行,并且通过扩展,在 OS X 上运行,因为它们没有 /proc 伪文件系统(是的,有 procfs,但默认情况下不安装在FreeBSD——除了被淘汰——而且在 OS X 下安装绝对不是微不足道的)。
    【解决方案2】:

    如果您确定 IO 对象代表一个文件,您可以尝试这样的操作

    path = io.path if io.respond_to?(:path)
    

    See documentation for File#path

    【讨论】:

    • IO 对象不代表一个文件对象,它代表一个 IO 对象。我想从中获取一个文件对象。以上将不起作用,因为 io 不响应路径
    • 如果有人从你下面重命名文件,这也不适用于 File 对象 -- f.path 将返回旧路径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2013-09-29
    相关资源
    最近更新 更多