微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

什么是Ruby中的可移植方式,以便在您尝试从中读取时检查STDIN将阻止的位置?

我想知道是否有一种可移植的方法来检查 Ruby脚本是否会阻止它尝试从STDIN读取.以下是适用于Unix(和Cygwin)但不适用于本机Win32的方法. (它基于我很久以前学过的Perl方法.)

$cat read-stdin.rb

#! /usr/bin/ruby
# test of reading from STDIN

require 'fcntl'

# Trace info on input objects
$stdout.sync=TRUE if $DEBUG         # make sure standard output and error synchronized
$stderr.print "ARGV=#{ARGV}\n" if $DEBUG
$stderr.print "ARGF=#{ARGF}\n" if $DEBUG

# See if input available,showing usage statement if not
blocking_stdin = FALSE
if (defined? Fcntl::F_GETFL) then
  $stderr.print "F_GETFL=#{Fcntl::F_GETFL} O_RDWR=#{Fcntl::O_RDWR}\n" if $DEBUG
  flags = STDIN.fcntl(Fcntl::F_GETFL,0) 
  $stderr.print "flags=#{flags}\n" if $DEBUG
  blocking_stdin = TRUE if ((flags & Fcntl::O_RDWR) == Fcntl::O_RDWR)
  $stderr.print "blocking_stdin=#{blocking_stdin}\n" if $DEBUG
end
if (blocking_stdin && (ARGV.length == 0)) then
  $stderr.print "usage: #{$0} [-]\n"
  Process.exit
end

# Read input and output it
$stderr.print "Input:\n" if $DEBUG
input_text = ARGF.read()
$stderr.print "Output:\n" if $DEBUG
print "#{input_text}\n"

这是没有调试的交互:

$grep -v DEBUG read-stdin.rb >| /tmp/simple-read-stdin.rb

$echo hey | ruby /tmp/simple-read-stdin.rb
hey

$ruby /tmp/simple-read-stdin.rb
usage: /tmp/simple-read-stdin.rb [-]

这是与调试的交互:

$echo hey | ruby -d read-stdin.rb
ARGV=
ARGF=ARGF
F_GETFL=3 O_RDWR=2
flags=65536
blocking_stdin=false
Input:
Output:
hey

$ruby -d read-stdin.rb
ARGV=
ARGF=ARGF
F_GETFL=3 O_RDWR=2
flags=98306
blocking_stdin=true
usage: read-stdin.rb [-]

解决方法

我不知道它是否普遍可移植,我也不知道它是否被认为是一个好主意(阻塞不是一个糟糕的概念)但IO中有一个 non-blocking read method.你可以像这样使用它:

chunk = nil

begin
  chunk = STDIN.read_nonblock(4096)
rescue Errno::EAGAIN
  # Handle the case if it would block
  chunk = 'nothing there...'
end

虽然,我认为如果没有指定像IO这样的缓冲区大小就行不通,它就会失败,但是通过使用循环解决这个问题应该很容易.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐