Forum: Ruby IO stream help

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
8c49880a7f274947b01d576c5828a5f6?d=identicon&s=25 Lon Baker (spdemac)
on 2006-04-13 09:07
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.
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-04-13 09:18
(Received via mailing list)
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
8c49880a7f274947b01d576c5828a5f6?d=identicon&s=25 Lon Baker (spdemac)
on 2006-04-13 17:46
Farrel Lifson 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.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-04-13 18:03
(Received via mailing list)
On Apr 13, 2006, at 11:46 AM, Lon Baker 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?
8c49880a7f274947b01d576c5828a5f6?d=identicon&s=25 Lon Baker (spdemac)
on 2006-04-13 18:18
Logan Capaldo wrote:
> On Apr 13, 2006, at 11:46 AM, Lon Baker 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?
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-04-13 18:47
(Received via mailing list)
On Fri, 14 Apr 2006, Lon Baker 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
8c49880a7f274947b01d576c5828a5f6?d=identicon&s=25 Lon Baker (spdemac)
on 2006-04-13 20:08
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.
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-04-13 21:20
(Received via mailing list)
On Fri, 14 Apr 2006, Lon Baker 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
8c49880a7f274947b01d576c5828a5f6?d=identicon&s=25 Lon Baker (spdemac)
on 2006-04-13 21:49
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.
This topic is locked and can not be replied to.