I am struggling with handling stdin and stdout in Ruby.
A java application I have responds works as a helper for an external
application by doing the following:
in = new BufferedReader(new InputStreamReader(System.in));
out = new PrintStream(System.out, true);
while((stream = in.readLine()).length() != 0) {
…
}
How can this be done in Ruby?
Any help would be grealy appreciated.
Something like this?
irb(main):007:0> while (!(input=$stdin.readline.chomp).length.zero?)
irb(main):008:1> puts input
irb(main):009:1> end
Hello
Hello
World
World
=> nil
Farrel L. wrote:
Something like this?
irb(main):007:0> while (!(input=$stdin.readline.chomp).length.zero?)
irb(main):008:1> puts input
irb(main):009:1> end
Hello
Hello
World
World
=> nil
Thank. But no luck.
It seems to hang waiting for input.
On Apr 13, 2006, at 11:46 AM, Lon B. wrote:
=> nil
Thank. But no luck.
It seems to hang waiting for input.
And you don’t want it to block for input? Are you trying to use
asynchronous IO or something?
On Fri, 14 Apr 2006, Lon B. wrote:
Would IO.popen or pipe be something to look at?
you need something like
Thread.new(cmd) do |cmd|
IO.popen(cmd, ‘r+’) do |pipe|
pipe.each do |line|
case line
when /request a/
pipe.puts ‘response a’
when /request b/
pipe.puts ‘response b’
end
end
end
end
… do other stuff while thread runs
if you don’t have ‘other stuff’ to do there’s no point in making it
async of
course though…
regards.
-a
Logan C. wrote:
On Apr 13, 2006, at 11:46 AM, Lon B. wrote:
=> nil
Thank. But no luck.
It seems to hang waiting for input.
And you don’t want it to block for input? Are you trying to use
asynchronous IO or something?
Yes it needs to be asynchronous.
The application is listening and responding to an external application.
It sits there listening for commands, processes them and responds with
its own commands.
Would IO.popen or pipe be something to look at?
Thanks for all the help.
I came up with the following code that works.
run = true
$stdout.sync = true
while run
input,output,error = IO::select( [$stdin], nil, nil, nil )
(input||[]).each {|s|
chunks = s.readline.split
case chunks[1]
when /INTF/
$stdout.puts “#{chunks[0]} #{chunks[1]} #{chunks[2]}”
when /QUIT/
$stdout.puts “#{chunks[0]} OK”
run = false
else
$stdout.puts “#{chunks[0]} OK”
end
}
end
This is used in a helper application for Communigate Pro mail servers.
Thank you! I did not realize that is what I had done.
The reason the previous suggested solution did not work, is that the
ruby script is not issuing a command, but is only responding to an
external process.
I thought this:
Thread.new(cmd) do |cmd|
IO.popen(cmd, ‘r+’) do |pipe|
Issued a command to the system.
Where my needs are for a script that is launched by and controlled by
the mail server.
Here is what happens with the mail server.
It issues commands in the following format:
109 FILE Queue/190016.msg\n
The number is the thread of communication, all requests and responses
start with this to tell the mail server what thread of communication it
is dealing with.
Its followed by a command, in this example “FILE”, which is followed by
the argument being the path to a file.
The server issues a request for each thread while waiting for the
responses, but will never issue a new request for a previously requested
thread.
Thanks again for the help. I will go back to the drawing board.
On Fri, 14 Apr 2006, Lon B. wrote:
(input||[]).each {|s|
}
end
This is used in a helper application for Communigate Pro mail servers.
but this is blocking? we thought you were needing asynchronous code?
what
you’ve written above will behave exactly like
STDOUT.sync = true
STDIN.each do |s|
chunks = s.readline.split
case chunks[1]
when /INTF/
puts “#{chunks[0]} #{chunks[1]} #{chunks[2]}”
when /QUIT/
puts “#{chunks[0]} OK”
else
puts “#{chunks[0]} OK”
end
end
that’s because what you’ve got above does this
here we block until io is ready to read. note that this can be
because
there is one char available or eof.
input,output,error = IO::select( [$stdin], nil, nil, nil )
here we block until a newline is read. note that a newline may
never be
read, or may take a very long time to arrive. esp if the
co-process is
buffering io. and that’s for the first iteration of the loop. on
the
second iteration this loop degrades into a ‘normally’ blocking call
(note
that select is not called again).
(input||[]).each {|s|
in otherwords what you’ve written is a compilcated way to do this
block until io ready. then block until a newline is read.
gets
not trying to be critical, but after reading your original posts the
above
left me confused. is there some other thread doing some work that must
procedd that’s not being shown?
regards.
-a