# Question about String.unpack

**URL:** <https://www.ruby-forum.com/t/question-about-string-unpack/54042>\
**Category:** Ruby\
**Created:** [February 21, 2006, 3:29pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042 "2006-02-21T15:29:01Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 21, 2006, 3:29pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/1 "2006-02-21T15:29:01Z")

</div>

Hi,

Say i’ve a C struct like that:

typedef struct {  
char name[30];  
double size;  
int age;  
char stuff;  
} enreg\_t;

This record is written in a file that i want to re-read with a Ruby  
script (just a toy example… to understand).

I’ve not found a “clean” way to unpack such a record…

My C compiler gives me a total sizeof of 48, so i use a  
fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather  
‘tricky’ (i suppose we don’t have always such a  
information). Furthermore, the first element is completed with  
garbage if the name field have less than 30 “useful” chars (“Doe”,  
for example).

I’m sure i’m missing something but i’ve not managed to find the right  
way to do that.

Any clue?

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 21, 2006, 8:14pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/2 "2006-02-21T20:14:09Z")

</div>

On Feb 21, 2006, at 9:28 AM, Eric J. wrote:

> for example).
> 
> I’m sure i’m missing something but i’ve not managed to find the right  
> way to do that.
> 
> ## Any clue?
> 
> Eric J., ne il y a 1443970729 secondes

there isn’t really a “clean” way to do this, since you are doing  
something inherently un-clean.  
However, to fix the string issue, a possible solution is:

str.gsub!(/\000.\*/, ‘’)

assuming of course that name is a c-string.

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 21, 2006, 8:20pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/3 "2006-02-21T20:20:17Z")

</div>

I’m curious about binary protocol parsing in ruby and have scratched  
around for some kind of BinaryReader-ish interface for strings. Seems  
like you could solve this if you know that your struct is in a string  
you could say:

str = fd.sysread(n)  
name = str.read\_str(30)  
size = str.read\_double  
age = str.read\_int  
stuff = str.read\_c

I was going to write a native extension to do this after I finish my  
current Ruby/AIO extension project. Unless there is something that  
does this already (maybe in a cleaner/more ruby-ish way?)

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 21, 2006, 8:51pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/4 "2006-02-21T20:51:21Z")

</div>

On Feb 21, 2006, at 2:19 PM, Jacob Repp wrote:

> I was going to write a native extension to do this after I finish my  
> current Ruby/AIO extension project. Unless there is something that  
> does this already (maybe in a cleaner/more ruby-ish way?)

This is pretty much exactly what unpack does anyway., except its one  
method that uses a format string. If you wanted a more stream  
oriented wrapper around this, you certainly could write one fairly  
easily.

ri String#unpack

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 22, 2006, 7:29am UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/5 "2006-02-22T07:29:33Z")

</div>

On Feb 21, 2006, at 6:28 AM, Eric J. wrote:

> script (just a toy example… to understand).
> 
> I’ve not found a “clean” way to unpack such a record…
> 
> My C compiler gives me a total sizeof of 48, so i use a  
> fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather

Your struct says char name[30] not 32…

> ‘tricky’ (i suppose we don’t have always such a  
> information). Furthermore, the first element is completed with  
> garbage if the name field have less than 30 “useful” chars (“Doe”,  
> for example).

Did you initialize the C struct correctly? You should zero out all  
of name.

> I’m sure i’m missing something but i’ve not managed to find the right  
> way to do that.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://segment7.net](http://segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 22, 2006, 2:33pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/6 "2006-02-22T14:33:27Z")

</div>

On 2/22/06, ts [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > > > > “E” == Eric H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:
> 
> > > My C compiler gives me a total sizeof of 48, so i use a  
> > > fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather
> 
> E\> Your struct says char name[30] not 32…
> 
> Yes, but there is alignement
> 
> He just want Z32 rather than A32

I would suggest that Z30xx would be a better choice.

pth

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 22, 2006, 11:11am UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/7 "2006-02-22T11:11:41Z")

</div>

> > > > > “E” == Eric H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> > My C compiler gives me a total sizeof of 48, so i use a  
> > fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather

E\> Your struct says char name[30] not 32…

Yes, but there is alignement

He just want Z32 rather than A32

biocluster1% cat a.c  
#include \<stdio.h\>  
#include \<string.h\>

typedef struct {  
char name[30];  
double size;  
int age;  
char stuff;  
} enreg\_t;

main()  
{  
FILE \*fd;  
enreg\_t enreg;  
strcpy(enreg.name, “abc”);  
enreg.size = 12.0;  
enreg.age = 12;  
enreg.stuff = ‘a’;  
fd = fopen(“aa”, “w”);  
fwrite(&enreg, sizeof(enreg), 1, fd);  
fclose(fd);  
}  
biocluster1%

biocluster1% ruby -e ‘p a = IO::read(“aa”); p a.unpack(“Z32dIC”)’  
“abc\000\030\373\377\277U\203\004\010tp\001@\360z\001@8\373\377\277K\205\004\010\200\270\024@\000\000\000\000\000\000(@\f\000\000\000ae\001@”  
[“abc”, 12.0, 12, 97]  
biocluster1%

Guy Decoux

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 22, 2006, 4:25pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/8 "2006-02-22T16:25:32Z")

</div>

ts [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> E\> Your struct says char name[30] not 32…
> 
> Yes, but there is alignement
> 
> He just want Z32 rather than A32

Thanks…

BTW: Eric, your message was not propagated to my Usenet Server…

---

<div class="post-metadata">

**Author:** ![cowboy\_x](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/d78d45/32.png) [@cowboy\_x](https://www.ruby-forum.com/u/cowboy_x)\
**Post date:** [February 22, 2006, 2:45pm UTC](https://www.ruby-forum.com/t/question-about-string-unpack/54042/9 "2006-02-22T14:45:48Z")

</div>

On Wed, Feb 22, 2006 at 04:19:07AM +0900, Jacob Repp wrote:

> I was going to write a native extension to do this after I finish my  
> current Ruby/AIO extension project. Unless there is something that  
> does this already (maybe in a cleaner/more ruby-ish way?)

Yes, I’ve needed one of these too (read + write). My application was  
handling a binary UDP protocol. String#unpack doesn’t support some of  
the bizarro data formating that this protocol seems to have, so I cooked  
up ReadBuffer/WriteBuffer[1] classes with a few methods a bit like those  
above.

…just my 2-pence-use-case.

dave

[1] [http://svn.badgers-in-foil.co.uk/alchemic/trunk/na\_protocol.rb](http://svn.badgers-in-foil.co.uk/alchemic/trunk/na_protocol.rb)
