红宝石......
我有一个由外部进程创建的IO对象,我需要从中获取文件名。 但是我似乎只能得到文件描述符(3),这对我来说并不是很有用。
有没有办法从这个对象获取文件名甚至获取文件对象?
我从通知程序获取IO对象。那么这也可能是获取文件路径的一种方式吗?
答案 0 :(得分:6)
how to get a the filename in C上有一个类似的问题,我将以红宝石的方式提出这个问题的答案。
假设io
是您的IO对象。以下代码为您提供文件名。
File.readlink("/proc/self/fd/#{io.fileno}")
例如,如果在为其创建io对象后删除了文件,则不起作用。使用此解决方案,您可以使用文件名,但不能使用File对象。
方法IO#for_fd
可以创建IO,它是任何给定整数filedescriptor的子类。通过执行以下操作获取fd的File对象:
File.for_fd(io.fileno)
不幸的是,这个File对象不知道文件名。
File.for_fd(io.fileno).path # => nil
我浏览了ruby-1.9.2来源。在创建文件对象之后,纯ruby中似乎无法操纵路径。
可以在C中创建对ruby的扩展,首先调用File#for_fd
,然后操作Files内部数据结构。这个源代码适用于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
readlink也可以放入File#for_fd_with_filename
定义。这个例子只是为了说明它是如何工作的。
答案 1 :(得分:0)