[RCR] IO#readn

M

Michael Neumann

Hi,

I suggest to add a method readn to the IO class (and to StringIO,
Socket...), which behaves similar to read(n), but raises an exception if
the returned string is not of size n.

class IO
def readn(n)
str = read(n)
raise if str.nil? or str.size != n
str
end
end

It's annoying to test for it in the application.

Regards,

Michael
 
A

Ara.T.Howard

Hi,

I suggest to add a method readn to the IO class (and to StringIO,
Socket...), which behaves similar to read(n), but raises an exception if
the returned string is not of size n.

class IO
def readn(n)
str = read(n)
raise if str.nil? or str.size != n
str
end
end

It's annoying to test for it in the application.

Regards,

Michael

don't you think the code will be just as long/annoying with a begin/rescue
block?

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it; and a weed grows, even though we do
| not love it. --Dogen
===============================================================================
 
M

Michael Neumann

don't you think the code will be just as long/annoying with a begin/rescue
block?

No, as I wouldn't use a rescue clause in this case. It's better to crash
early than proceed with a wrong value.

I never liked it that read(4) might return only 3 characters.

Regards,

Michael
 
S

Simon Strandgaard

On Saturday 19 June 2004 19:01, Michael Neumann wrote:
[snip]
I never liked it that read(4) might return only 3 characters.

Wouldn't it be better then to change the behavier of #read itself, so
it fails per default in case the specified number of bytes cannot be read.

with ruby2 we should try to break as much as possible, and hopefully
get it right.

#readn smells too much like workaround :)
 
M

Michael Neumann

On Saturday 19 June 2004 19:01, Michael Neumann wrote:
[snip]
I never liked it that read(4) might return only 3 characters.

Wouldn't it be better then to change the behavier of #read itself, so
it fails per default in case the specified number of bytes cannot be read.

with ruby2 we should try to break as much as possible, and hopefully
get it right.

Right. You have my vote for it!

But I fear, as #read resembles the UNIX read(2) syscall, this change
will not happen in Ruby2.

Regards,

Michael
 
S

Sean O'Dell

On Saturday 19 June 2004 19:01, Michael Neumann wrote:
[snip]
I never liked it that read(4) might return only 3 characters.

Wouldn't it be better then to change the behavier of #read itself, so
it fails per default in case the specified number of bytes cannot be read.

with ruby2 we should try to break as much as possible, and hopefully
get it right.

#readn smells too much like workaround :)

I agree, a method called to read n bytes should raise an exception when it
cannot.

Sean O'Dell
 
R

Reimer Behrends

Sean O'Dell ([email protected]) wrote:
[...]
I agree, a method called to read n bytes should raise an exception when it
cannot.

Except that the semantics of read() specify that _at most_ n bytes will
be read. There are important cases where you want these semantics, such
as when reading from a non-blocking socket or pipe or when reading a
file in chunks without wanting to bother to find out what exactly the
size of the last chunk will be (which can be impossible if the file is
not seekable).

Reimer Behrends
 
S

Sean O'Dell

Sean O'Dell ([email protected]) wrote:
[...]
I agree, a method called to read n bytes should raise an exception when
it cannot.

Except that the semantics of read() specify that _at most_ n bytes will
be read. There are important cases where you want these semantics, such
as when reading from a non-blocking socket or pipe or when reading a
file in chunks without wanting to bother to find out what exactly the
size of the last chunk will be (which can be impossible if the file is
not seekable).

Yep, you're right...I guess that would apply even in a scripted environment.

Sean O'Dell
 
J

Joel VanderWerf

Michael said:
Hi,

I suggest to add a method readn to the IO class (and to StringIO,
Socket...), which behaves similar to read(n), but raises an exception if
the returned string is not of size n.

class IO
def readn(n)
str = read(n)
raise if str.nil? or str.size != n
str
end
end

Here's an option that gives the programmer the option of chosing whether
to to use "at most" or "exactly" semantics. As bonus, it also allows "at
least" and "0 or N, but nothing in between" semantics.

Also, since it doesn't accept a Fixnum argument, it forces the
programmer to be clear about the chosen semantics.

----

module ReadExt
def read_inclusive(enum = nil)
str = read(enum && enum.max)
str_size = str ? str.size : 0
if enum and not enum.include?(str_size)
raise RangeError
end
str
end
end

require 'stringio'

class IO; include ReadExt; end
class StringIO; include ReadExt; end

io = StringIO.new

io.write(('a'..'z').to_a)

io.rewind
p io.read_inclusive(20..30) # ==> "abcdefghijklmnopqrstuvwxyz"
p io.read_inclusive # ==> ""
begin
p io.read_inclusive(5..5)
rescue RangeError
puts "nothing left to read" # ==> nothing left to read
end

io.rewind
p io.read_inclusive(0..10) # ==> "abcdefghij"

io.rewind
p io.read_inclusive(20..20) # ==> "abcdefghijklmnopqrst"

begin
io.rewind
p io.read_inclusive(30..30)
rescue RangeError
puts "alphabet underflow" # ==> alphabet underflow
end

io.rewind
p io.read_inclusive # ==> "abcdefghijklmnopqrstuvwxyz"
p io.read_inclusive(0..100) # ==> nil

io.rewind
3.times do
# automatically checks for "complete" blocks of 13
p io.read_inclusive([0,13])
# ==> "abcdefghijklm"
# ==> "nopqrstuvwxyz"
# ==> nil
end
 
A

Ara.T.Howard

No, as I wouldn't use a rescue clause in this case. It's better to crash
early than proceed with a wrong value.

I never liked it that read(4) might return only 3 characters.

Regards,

Michael

but another read may give one more byte - then you'd have your 4? even if one
implemented IO#read(n) i'd think you'd want:

class IO
def readn n
buf = ''
buf << read(n - buf.size) until buf.size == n
buf
end
end

which give you what you want (n bytes), or throws EOFError.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it; and a weed grows, even though we do
| not love it. --Dogen
===============================================================================
 
A

Ara.T.Howard

Sean O'Dell ([email protected]) wrote:
[...]
I agree, a method called to read n bytes should raise an exception when it
cannot.

Except that the semantics of read() specify that _at most_ n bytes will
be read. There are important cases where you want these semantics, such
as when reading from a non-blocking socket or pipe or when reading a
file in chunks without wanting to bother to find out what exactly the
size of the last chunk will be (which can be impossible if the file is
not seekable).

Reimer Behrends

exactly. if don't like the way it works now, try writing code which reads
from network socket using a read(n) which throws exceptions. THAT will be
ugly...

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it; and a weed grows, even though we do
| not love it. --Dogen
===============================================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

EventMachine or GServer? 4
Relative seeks on string IO 2
Queue/IO blocking in threads 1
ChatBot 4
StringIO#readbytes 7
Improving the web page download code. 5
Translater + module + tkinter 1
RCR for Range.rand 0

Members online

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,375
Latest member
FelishaCma

Latest Threads

Top