How do I properly read from a pipe?

I want to pass some XML string to ‘tidy’ so it formats it nicely. So I
do:

document = ‘whatever

IO.popen(‘tidy -xml -i’, ‘r+’) do |p|
p.write document
p.close

read back the formatted output:

p.read
end

But then Ruby complains that I’m reading from a closed stream (when I do
“p.read”). But tidy has do see EOF before it begins to process its
input!

So how do I let the programs I’m piping to think that there’s no more
input?

Albert S. wrote in post #1051155:

I want to pass some XML string to ‘tidy’ so it formats it nicely. So I
do:

document = ‘whatever

IO.popen(‘tidy -xml -i’, ‘r+’) do |p|
p.write document
p.close

read back the formatted output:

p.read
end

But then Ruby complains that I’m reading from a closed stream (when I do
“p.read”). But tidy has do see EOF before it begins to process its
input!

So how do I let the programs I’m piping to think that there’s no more
input?

Not sure about the EOF, but I think you need to use IO#close_write
instead of IO#close.

HTH,

  • Lars

Lars Mai wrote in post #1051172:

So how do I let the programs I’m piping to think that there’s no more
input?

Not sure about the EOF, but I think you need to use IO#close_write
instead of IO#close.

Thanks, it now works!

(I need to refresh my memory with Richard Stevens’ Unix book…)

Robert K. wrote in post #1051182:

:slight_smile: There’s one more thing I would do: put the writing into a separate
thread. If buffers are not sufficiently large enough your version
deadlocks.

Ah, a good point.

Please correct me if I’m wrong: this isn’t necessary if the piped-to
program (e.g. ‘sort’) reads its entire input before doing output.

Albert S. wrote in post #1051173:

Lars Mai wrote in post #1051172:

So how do I let the programs I’m piping to think that there’s no more
input?

Not sure about the EOF, but I think you need to use IO#close_write
instead of IO#close.

Thanks, it now works!

(I need to refresh my memory with Richard Stevens’ Unix book…)

:slight_smile: There’s one more thing I would do: put the writing into a separate
thread. If buffers are not sufficiently large enough your version
deadlocks.

Kind regards

robert