[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

IO.readint ?

Rolando Abarca

10/12/2006 3:35:00 PM

Hi all,
I'm parsing a binary file, and need to read an integer, something I
would do in C like this:

int b;
read(f, &b, sizeof(int));

obviously considering endianness. I'm pretty sure there has to be a
faster way to do it, but this is how I'm doing it right now (as you
can see, pretty naive):

class IO
# read int, assume little endian
def geti
c1 = getc
c2 = getc
c3 = getc
c4 = getc
c4 << 3*8 | c3 << 2*8 | c2 << 8 | c1
end
end

What would be the ruby-way to do it?
thanks for any tip...
--
rolando -- [[ knowledge is empty, fill it ]] --
"Tam pro papa quam pro rege bibunt omnes sine lege."

15 Answers

Tim Pease

10/12/2006 3:50:00 PM

0

On 10/12/06, Rolando Abarca <funkaster@gmail.com> wrote:
> Hi all,
> I'm parsing a binary file, and need to read an integer, something I
> would do in C like this:
>
> int b;
> read(f, &b, sizeof(int));
>
> obviously considering endianness. I'm pretty sure there has to be a
> faster way to do it, but this is how I'm doing it right now (as you
> can see, pretty naive):
>
> class IO
> # read int, assume little endian
> def geti
> c1 = getc
> c2 = getc
> c3 = getc
> c4 = getc
> c4 << 3*8 | c3 << 2*8 | c2 << 8 | c1
> end
> end
>
> What would be the ruby-way to do it?
> thanks for any tip...


class IO
def geti( endian = :little )
str = self.read( 4 )
str = str.reverse if endian == :little
str.unpack( 'N' )[0]
end
end


The default for this method is to return the integer in little endian
byte order. You can change this by passing :big as an argument ...

io.geti :big

It does not have to be :big, but I'm just following the metaphor of
using :little for little endian byte order.

Blessings,
TwP

Kalman Noel

10/12/2006 4:10:00 PM

0

Tim Pease:
> On 10/12/06, Rolando Abarca <funkaster@gmail.com> wrote:
>> int b;
>> read(f, &b, sizeof(int));
> class IO
> def geti( endian = :little )
> str = self.read( 4 )
> str = str.reverse if endian == :little
> str.unpack( 'N' )[0]
> end
> end

Yet you cannot be sure that sizeof(int) is 4.

Kalman

Ross Bamford

10/12/2006 4:33:00 PM

0

On Fri, 2006-10-13 at 00:35 +0900, Rolando Abarca wrote:
> Hi all,
> I'm parsing a binary file, and need to read an integer,

Check out String#unpack:

(dta = File.read('ints.bin')).unpack('I' * (dta.length / 4))
# => [1234, 2345, 3456]

It has different type specifiers for endianness and so on. Also, if you
gotta crawl through the file, you can tell IO#read how many bytes you
want:

File.open('ints.bin') { |f| puts f.read(4).unpack('I') until f.eof? }
# 1234
# 2345
# 3456
# => nil

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk


Rolando Abarca

10/12/2006 5:10:00 PM

0

On 10/12/06, Kalman Noel <invalid@gmx.net> wrote:
> Yet you cannot be sure that sizeof(int) is 4.

no, but in my case works just fine. it will always be a 4 byte unsigned integer.

> Kalman

regards,
--
rolando -- [[ knowledge is empty, fill it ]] --
"Tam pro papa quam pro rege bibunt omnes sine lege."

Rolando Abarca

10/12/2006 5:10:00 PM

0

Thanks a lot, I'll try that!!!

On 10/12/06, Tim Pease <tim.pease@gmail.com> wrote:
> class IO
> def geti( endian = :little )
> str = self.read( 4 )
> str = str.reverse if endian == :little
> str.unpack( 'N' )[0]
> end
> end
>
>
> The default for this method is to return the integer in little endian
> byte order. You can change this by passing :big as an argument ...
>
> io.geti :big
>
> It does not have to be :big, but I'm just following the metaphor of
> using :little for little endian byte order.
>
> Blessings,
> TwP

--
rolando -- [[ knowledge is empty, fill it ]] --
"Tam pro papa quam pro rege bibunt omnes sine lege."

Tim Pease

10/12/2006 5:16:00 PM

0

On 10/12/06, Rolando Abarca <funkaster@gmail.com> wrote:
> Thanks a lot, I'll try that!!!
>

No problem. Take a look at bit-struct if you find yourself needing to
do some more complex packing and unpacking of binary data ...

http://raa.ruby-lang.org/project/b...

Blessings,
TwP

Ara.T.Howard

10/12/2006 5:44:00 PM

0

Tim Pease

10/12/2006 6:08:00 PM

0

On 10/12/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
> On Fri, 13 Oct 2006, Tim Pease wrote:
> >
> > No problem. Take a look at bit-struct if you find yourself needing to
> > do some more complex packing and unpacking of binary data ...
> >
> > http://raa.ruby-lang.org/project/b...
> >
> > Blessings,
> > TwP
>
> have you been using this for your stuff tim?
>

No, we've just been parsing very large pixel images. No complex data
structures. Read four bytes, mask off the hamming code and error
bits, store the pixel data in an mmap cache, repeat until EOF.

From the bit-struct readme ...

"BitStruct is most efficient when your data is primarily treated as a
binary string, and only secondarily treated as a data structure. (For
instance, you are routing packets from one socket to another, possibly
looking at one or two fields as it passes through or munging some
headers.) If accessor operations are a bottleneck, a better approach
is to define a class that wraps an array and uses pack/unpack when the
object needs to behave like a binary string."


TwP

Ara.T.Howard

10/12/2006 6:27:00 PM

0

Hal E. Fulton

10/13/2006 1:09:00 AM

0

Rolando Abarca wrote:
--
rolando -- [[ knowledge is empty, fill it ]] --
"Tam pro papa quam pro rege bibunt omnes sine lege."


Quicquid Venus imperat, labor est suavis...


;)
Hal