# IO stream help

**URL:** <https://www.ruby-forum.com/t/io-stream-help/93894>\
**Category:** Ruby\
**Created:** [April 13, 2006, 9:07am UTC](https://www.ruby-forum.com/t/io-stream-help/93894 "2006-04-13T09:07:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 9:07am UTC](https://www.ruby-forum.com/t/io-stream-help/93894/1 "2006-04-13T09:07:57Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 9:18am UTC](https://www.ruby-forum.com/t/io-stream-help/93894/2 "2006-04-13T09:18:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 5:46pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/3 "2006-04-13T17:46:26Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 6:03pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/4 "2006-04-13T18:03:06Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 6:47pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/5 "2006-04-13T18:47:03Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 6:18pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/6 "2006-04-13T18:18:45Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 8:08pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/7 "2006-04-13T20:08:33Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 9:49pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/8 "2006-04-13T21:49:40Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![spdemac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@spdemac](https://www.ruby-forum.com/u/spdemac)\
**Post date:** [April 13, 2006, 9:20pm UTC](https://www.ruby-forum.com/t/io-stream-help/93894/9 "2006-04-13T21:20:39Z")

</div>

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
