# Reading and writing a binary file

**URL:** https://rubytalk.org/t/reading-and-writing-a-binary-file/17074
**Category:** ruby-talk
**Created:** [21 March 2005 13:24 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074 "2005-03-21T13:24:50Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Chris\_Guenther](https://avatars.discourse-cdn.com/v4/letter/c/bc8723/32.png) [@Chris\_Guenther](https://rubytalk.org/u/Chris_Guenther)
#### Post date: [21 March 2005 13:24 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/1 "2005-03-21T13:24:50Z")

</div>

Hi,

I am having trouble reading values from an existing (or maybe not yet  
exisiting) binary file:  
My target is to open a binary file for reading and writing (if it does not  
exisit it should be created).  
If the file was not yes existing I'd like to fill it with binary data to a  
certain predefined size.  
Later on I'd like to position my file position, and read and write whatever  
I like.

The following piece does not work as intended:

&nbsp;&nbsp;require 'pp'  
&nbsp;&nbsp;UNDER\_UNIX = CONFIG['target\_os'].to\_s.index('linux')!=nil  
&nbsp;&nbsp;filename='foo.bin'  
&nbsp;&nbsp;size=1024  
&nbsp;&nbsp;dont\_write=FileTest.exists?(filename) && File.stat(filename).size==size  
&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd=File.open(filename,"ab+")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.binmode unless UNDER\_UNIX # assuming !UNIX=WINDOWS  
&nbsp;&nbsp;rescue =\> e  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pp e  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd=File.open(filename,"wb+")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "opened #{filename} with 'wib+'"  
&nbsp;&nbsp;end

&nbsp;&nbsp;fd.sync=true  
&nbsp;&nbsp;fd.seek(0)  
&nbsp;&nbsp;unless dont\_write  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*(size)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# OK now I really have a file of size 1024 with a binay 0 contents  
&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;###.... then sometime later using the same file descriptor (fd) :  
&nbsp;&nbsp;&nbsp;&nbsp;requestes\_stream\_position = 900  
&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=(requestes\_stream\_position)  
&nbsp;&nbsp;&nbsp;&nbsp;p "tell=#{fd.tell}"  
&nbsp;&nbsp;&nbsp;&nbsp;# Now please read 30 binary 0s into a binary string  
&nbsp;&nbsp;&nbsp;&nbsp;bin\_value=fd.read(30)

&nbsp;&nbsp;&nbsp;&nbsp;#### I ASSUMED THAT bin\_value now is a "binary string of size 30", but  
unfortunately it is nil !!!

Thanks in adcance,  
C.

---

<div class="post-metadata">

### Author: ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)
#### Post date: [21 March 2005 15:14 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/2 "2005-03-21T15:14:54Z")

</div>

"Chris Guenther" \<chris\_guenther@freenet.de\> schrieb im Newsbeitrag  
news:d1mhu3$bi6$1@news.mch.sbs.de...

> Hi,
> 
> I am having trouble reading values from an existing (or maybe not yet  
> exisiting) binary file:  
> My target is to open a binary file for reading and writing (if it does

not

> exisit it should be created).  
> If the file was not yes existing I'd like to fill it with binary data to

a

> certain predefined size.  
> Later on I'd like to position my file position, and read and write

whatever

> I like.
> 
> The following piece does not work as intended:
> 
> &nbsp;&nbsp;require 'pp'  
> &nbsp;&nbsp;UNDER\_UNIX = CONFIG['target\_os'].to\_s.index('linux')!=nil  
> &nbsp;&nbsp;filename='foo.bin'  
> &nbsp;&nbsp;size=1024  
> &nbsp;&nbsp;dont\_write=FileTest.exists?(filename) &&

File.stat(filename).size==size

> &nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd=File.open(filename,"ab+")  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.binmode unless UNDER\_UNIX # assuming !UNIX=WINDOWS  
> &nbsp;&nbsp;rescue =\> e  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pp e  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd=File.open(filename,"wb+")  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "opened #{filename} with 'wib+'"  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;fd.sync=true  
> &nbsp;&nbsp;fd.seek(0)  
> &nbsp;&nbsp;unless dont\_write  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*(size)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# OK now I really have a file of size 1024 with a binay 0 contents  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;###.... then sometime later using the same file descriptor (fd) :  
> &nbsp;&nbsp;&nbsp;&nbsp;requestes\_stream\_position = 900  
> &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=(requestes\_stream\_position)  
> &nbsp;&nbsp;&nbsp;&nbsp;p "tell=#{fd.tell}"  
> &nbsp;&nbsp;&nbsp;&nbsp;# Now please read 30 binary 0s into a binary string  
> &nbsp;&nbsp;&nbsp;&nbsp;bin\_value=fd.read(30)
> 
> &nbsp;&nbsp;&nbsp;&nbsp;#### I ASSUMED THAT bin\_value now is a "binary string of size 30",

but

> unfortunately it is nil !!!
> 
> Thanks in adcance,  
> C.

I don't know what you're doing wrong. Your script works fine for me.  
Btw, you don't close the fd.

Here's how I'd do it:

filename='foo.bin'  
size=1024

File.open(filename, "ab+") do |fd|  
&nbsp;&nbsp;fd.seek(0, IO::SEEK\_END)

&nbsp;&nbsp;if fd.tell \< size  
&nbsp;&nbsp;&nbsp;&nbsp;fd.seek 0  
&nbsp;&nbsp;&nbsp;&nbsp;fd.write( "\000" \* size );  
&nbsp;&nbsp;elsif fd.tell \> size  
&nbsp;&nbsp;&nbsp;&nbsp;# if you need the file to be exact this size  
&nbsp;&nbsp;&nbsp;&nbsp;fd.truncate size  
&nbsp;&nbsp;end

&nbsp;&nbsp;requestes\_stream\_position = 900  
&nbsp;&nbsp;fd.seek requestes\_stream\_position

&nbsp;&nbsp;bin\_value = fd.read(30)  
&nbsp;&nbsp;p bin\_value  
end

Notes:

- don't change binmode depending on platform, always use "b" for binary  
files.

- use File.open with block for proper close / cleanup

Kind regards

&nbsp;&nbsp;&nbsp;&nbsp;robert

---

<div class="post-metadata">

### Author: ![Chris\_Gunther](https://avatars.discourse-cdn.com/v4/letter/c/4da419/32.png) [@Chris\_Gunther](https://rubytalk.org/u/Chris_Gunther)
#### Post date: [22 March 2005 11:49 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/3 "2005-03-22T11:49:51Z")

</div>

Chris Guenther wrote:

> Hi,
> 
> I am having trouble reading values from an existing (or maybe not yet  
> exisiting) binary file:  
> My target is to open a binary file for reading and writing (if it does not  
> exisit it should be created).  
> If the file was not yes existing I'd like to fill it with binary data to a  
> certain predefined size.  
> Later on I'd like to position my file position, and read and write whatever  
> I like.
> 
> The following piece does not work as intended:
> 
> &nbsp;&nbsp;require 'pp'  
> &nbsp;&nbsp;UNDER\_UNIX = CONFIG['target\_os'].to\_s.index('linux')!=nil  
> &nbsp;&nbsp;filename='foo.bin'  
> &nbsp;&nbsp;size=1024  
> &nbsp;&nbsp;dont\_write=FileTest.exists?(filename) && File.stat(filename).size==size  
> &nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd=File.open(filename,"ab+")  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.binmode unless UNDER\_UNIX # assuming !UNIX=WINDOWS  
> &nbsp;&nbsp;rescue =\> e  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pp e  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd=File.open(filename,"wb+")  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "opened #{filename} with 'wib+'"  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;fd.sync=true  
> &nbsp;&nbsp;fd.seek(0)  
> &nbsp;&nbsp;unless dont\_write  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*(size)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# OK now I really have a file of size 1024 with a binay 0 contents  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;###.... then sometime later using the same file descriptor (fd) :  
> &nbsp;&nbsp;&nbsp;&nbsp;requestes\_stream\_position = 900  
> &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=(requestes\_stream\_position)  
> &nbsp;&nbsp;&nbsp;&nbsp;p "tell=#{fd.tell}"  
> &nbsp;&nbsp;&nbsp;&nbsp;# Now please read 30 binary 0s into a binary string  
> &nbsp;&nbsp;&nbsp;&nbsp;bin\_value=fd.read(30)
> 
> &nbsp;&nbsp;&nbsp;&nbsp;#### I ASSUMED THAT bin\_value now is a "binary string of size 30", but  
> unfortunately it is nil !!!
> 
> Thanks in adcance,  
> C.

Thanks Robert,

you are absolutely right with your remarks using a block. The code I posted was just a small copied fraction of the real code, in which I cannor use a block because the same fd will be stored in a hash for later usage by another method.  
Anyway, meanwhile I found the cause of this problem (again you are right, it was not in the code I posted) , but now I have another related problem that tricks my mind. I am trying to patch binary data in a file.  
Unfortunately the data I am patching is not the data I get when reading it back from the patched binary file.  
Any ideas??

Thanks again in advance,  
Chris

#!/usr/bin/env ruby

FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
[?c,?a,?f,?e].pack('cccc')

File.open(FNAME,"ab+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
}

File.truncate(FNAME,FSIZE)

File.open(FNAME,"ab+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data=fd.read(FSIZE)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[OFFSET,VALUE.length]=VALUE  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(data)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{data[OFFSET,VALUE.length]}'"  
}

File.truncate(FNAME,FSIZE)  
File.open(FNAME,"ab+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
}

---

<div class="post-metadata">

### Author: ![Chris\_Gunther](https://avatars.discourse-cdn.com/v4/letter/c/4da419/32.png) [@Chris\_Gunther](https://rubytalk.org/u/Chris_Gunther)
#### Post date: [22 March 2005 11:29 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/4 "2005-03-22T11:29:51Z")

</div>

Thanks Robert,

you are absolutely right with your remarks using a block. The code I posted was just a small copied fraction of the real code, in which I cannor use a block because the same fd will be stored in a hash for later usage by another method.  
Anyway, meanwhile I found the cause of this problem (again you are right, it was not in the code I posted) , but now I have another related problem that tricks my mind. I am trying to patch binary data in a file.  
Unfortunately the data I am patching is not the data I get when reading it back from the patched binary file.  
Any ideas??

Thanks again in advance,  
Chris

#!/usr/bin/env ruby

FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
[?c,?a,?f,?e].pack('cccc')

File.open(FNAME,"ab+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
}

File.truncate(FNAME,FSIZE)

File.open(FNAME,"ab+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data=fd.read(FSIZE)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[OFFSET,VALUE.length]=VALUE  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(data)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{data[OFFSET,VALUE.length]}'"  
}

File.truncate(FNAME,FSIZE)  
File.open(FNAME,"ab+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
}

---

<div class="post-metadata">

### Author: ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)
#### Post date: [22 March 2005 13:59 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/5 "2005-03-22T13:59:53Z")

</div>

"Chris Günther" \<cg\_@gmx.de\> schrieb im Newsbeitrag  
news:42400070.2050609@gmx.de...

> Thanks Robert,
> 
> you are absolutely right with your remarks using a block. The code I  
> posted was just a small copied fraction of the real code, in which I  
> cannor use a block because the same fd will be stored in a hash for  
> later usage by another method.  
> Anyway, meanwhile I found the cause of this problem (again you are  
> right, it was not in the code I posted) , but now I have another related  
> problem that tricks my mind. I am trying to patch binary data in a file.  
> Unfortunately the data I am patching is not the data I get when reading  
> it back from the patched binary file.  
> Any ideas??
> 
> Thanks again in advance,  
> Chris
> 
> #!/usr/bin/env ruby
> 
> FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
> [?c,?a,?f,?e].pack('cccc')
> 
> File.open(FNAME,"ab+") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
> }
> 
> File.truncate(FNAME,FSIZE)
> 
> File.open(FNAME,"ab+") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data=fd.read(FSIZE)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[OFFSET,VALUE.length]=VALUE  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(data)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{data[OFFSET,VALUE.length]}'"  
> }

You truncate too often:

> File.truncate(FNAME,FSIZE)

> File.open(FNAME,"ab+") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
> }

Careful when you're copying and pasting.

Regards

&nbsp;&nbsp;&nbsp;&nbsp;robert

---

<div class="post-metadata">

### Author: ![Pit](https://avatars.discourse-cdn.com/v4/letter/p/f14d63/32.png) [@Pit](https://rubytalk.org/u/Pit)
#### Post date: [22 March 2005 18:56 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/6 "2005-03-22T18:56:39Z")

</div>

Chris Günther schrieb:

> ... I am trying to patch binary data in a file.  
> Unfortunately the data I am patching is not the data I get when reading it back from the patched binary file.  
> Any ideas??  
> ...  
> File.open(FNAME,"ab+") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> ...

Hi Chris,

it seems that the mode "ab+" is your problem. According to [1], "a+" means open the file for reading and writing, starting at the end of the file. This also means (at least on windows), that the end of file is position 0. So what you are doing above is writing the patched data after the end of the original file.

For patching a binary file I'd change your code to:

&nbsp;&nbsp;&nbsp;FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
&nbsp;&nbsp;&nbsp;[?c,?a,?f,?e].pack('cccc')

&nbsp;&nbsp;&nbsp;# "wb+" for initial data: truncate existing content  
&nbsp;&nbsp;&nbsp;File.open(FNAME,"wb+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;# "rb+" for the patch: open at the beginning  
&nbsp;&nbsp;&nbsp;File.open(FNAME,"rb+") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(VALUE)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{VALUE}'"  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;# "rb" for reading the data  
&nbsp;&nbsp;&nbsp;File.open(FNAME,"rb") {|fd|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
&nbsp;&nbsp;&nbsp;}

Regards,  
Pit

[1] [class IO - RDoc Documentation](http://www.ruby-doc.org/core/classes/IO.html)

---

<div class="post-metadata">

### Author: ![Carlos](https://avatars.discourse-cdn.com/v4/letter/c/ecae2f/32.png) [@Carlos](https://rubytalk.org/u/Carlos)
#### Post date: [22 March 2005 19:20 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/7 "2005-03-22T19:20:19Z")

</div>

[Chris Günther \<cg\_@gmx.de\>, 2005-03-22 12.29 CET]

> Thanks Robert,
> 
> you are absolutely right with your remarks using a block. The code I  
> posted was just a small copied fraction of the real code, in which I  
> cannor use a block because the same fd will be stored in a hash for  
> later usage by another method.  
> Anyway, meanwhile I found the cause of this problem (again you are  
> right, it was not in the code I posted) , but now I have another related  
> problem that tricks my mind. I am trying to patch binary data in a file.  
> Unfortunately the data I am patching is not the data I get when reading  
> it back from the patched binary file.  
> Any ideas??

All your problems come from the fact that your are opening the file for  
appending ("ab+") instead of for reading ("r+b"). With "ab+", you can set fd.pos=0,  
if you want, but it will always write at the end of file.

---

<div class="post-metadata">

### Author: ![Chris\_Gunther](https://avatars.discourse-cdn.com/v4/letter/c/4da419/32.png) [@Chris\_Gunther](https://rubytalk.org/u/Chris_Gunther)
#### Post date: [22 March 2005 17:24 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/8 "2005-03-22T17:24:50Z")

</div>

Robert Klemme wrote:

> "Chris Günther" \<cg\_@gmx.de\> schrieb im Newsbeitrag  
> news:42400070.2050609@gmx.de...
> 
> > Thanks Robert,
> > 
> > you are absolutely right with your remarks using a block. The code I  
> > posted was just a small copied fraction of the real code, in which I  
> > cannor use a block because the same fd will be stored in a hash for  
> > later usage by another method.  
> > Anyway, meanwhile I found the cause of this problem (again you are  
> > right, it was not in the code I posted) , but now I have another related  
> > problem that tricks my mind. I am trying to patch binary data in a file.  
> > Unfortunately the data I am patching is not the data I get when reading  
> > it back from the patched binary file.  
> > Any ideas??
> > 
> > Thanks again in advance,  
> > Chris
> > 
> > #!/usr/bin/env ruby
> > 
> > FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
> > [?c,?a,?f,?e].pack('cccc')
> > 
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > &nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
> > }
> > 
> > File.truncate(FNAME,FSIZE)
> > 
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > &nbsp;&nbsp;&nbsp;&nbsp;data=fd.read(FSIZE)  
> > &nbsp;&nbsp;&nbsp;&nbsp;data[OFFSET,VALUE.length]=VALUE  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.write(data)  
> > &nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{data[OFFSET,VALUE.length]}'"  
> > }
> 
> You truncate too often:
> 
> > File.truncate(FNAME,FSIZE)
> 
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
> > &nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
> > &nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
> > &nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
> > }
> 
> Careful when you're copying and pasting.
> 
> Regards
> 
> &nbsp;&nbsp;&nbsp;&nbsp;robert

I dont see your point. I have to truncate after every write to ensure the file size does not change. Where is the connection to the problem that the read value does not match the written value ?

regards,  
C.

---

<div class="post-metadata">

### Author: ![Chris\_Gunther](https://avatars.discourse-cdn.com/v4/letter/c/4da419/32.png) [@Chris\_Gunther](https://rubytalk.org/u/Chris_Gunther)
#### Post date: [22 March 2005 17:24 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/9 "2005-03-22T17:24:51Z")

</div>

Robert Klemme wrote:

> "Chris Günther" \<cg\_@gmx.de\> schrieb im Newsbeitrag  
> news:42400070.2050609@gmx.de...
> 
> > Thanks Robert,
> > 
> > you are absolutely right with your remarks using a block. The code I  
> > posted was just a small copied fraction of the real code, in which I  
> > cannor use a block because the same fd will be stored in a hash for  
> > later usage by another method.  
> > Anyway, meanwhile I found the cause of this problem (again you are  
> > right, it was not in the code I posted) , but now I have another related  
> > problem that tricks my mind. I am trying to patch binary data in a file.  
> > Unfortunately the data I am patching is not the data I get when reading  
> > it back from the patched binary file.  
> > Any ideas??
> > 
> > Thanks again in advance,  
> > Chris
> > 
> > #!/usr/bin/env ruby
> > 
> > FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
> > [?c,?a,?f,?e].pack('cccc')
> > 
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > &nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
> > }
> > 
> > File.truncate(FNAME,FSIZE)
> > 
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > &nbsp;&nbsp;&nbsp;&nbsp;data=fd.read(FSIZE)  
> > &nbsp;&nbsp;&nbsp;&nbsp;data[OFFSET,VALUE.length]=VALUE  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.write(data)  
> > &nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{data[OFFSET,VALUE.length]}'"  
> > }
> 
> You truncate too often:
> 
> > File.truncate(FNAME,FSIZE)
> 
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
> > &nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
> > &nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
> > &nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
> > }
> 
> Careful when you're copying and pasting.
> 
> Regards
> 
> &nbsp;&nbsp;&nbsp;&nbsp;robert

I dont see your point. I have to truncate after every write to ensure the file size does not change. Where is the connection to the problem that the read value does not match the written value ?

regards,  
C.

---

<div class="post-metadata">

### Author: ![Chris\_Gunther](https://avatars.discourse-cdn.com/v4/letter/c/4da419/32.png) [@Chris\_Gunther](https://rubytalk.org/u/Chris_Gunther)
#### Post date: [23 March 2005 16:49 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/10 "2005-03-23T16:49:48Z")

</div>

Pit Capitain wrote:

> Chris Günther schrieb:
> 
> > ... I am trying to patch binary data in a file.  
> > Unfortunately the data I am patching is not the data I get when reading it back from the patched binary file.  
> > Any ideas??  
> > ...  
> > File.open(FNAME,"ab+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;fd.pos=0  
> > ...
> 
> Hi Chris,
> 
> it seems that the mode "ab+" is your problem. According to [1], "a+" means open the file for reading and writing, starting at the end of the file. This also means (at least on windows), that the end of file is position 0. So what you are doing above is writing the patched data after the end of the original file.
> 
> For patching a binary file I'd change your code to:
> 
> &nbsp;&nbsp;FNAME, FSIZE, OFFSET, VALUE = 'foooo.dat', 1024, 32,  
> &nbsp;&nbsp;[?c,?a,?f,?e].pack('cccc')
> 
> &nbsp;&nbsp;# "wb+" for initial data: truncate existing content  
> &nbsp;&nbsp;File.open(FNAME,"wb+") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bin\_data = [0].pack('c')\*FSIZE  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(bin\_data)  
> &nbsp;&nbsp;}
> 
> &nbsp;&nbsp;# "rb+" for the patch: open at the beginning  
> &nbsp;&nbsp;File.open(FNAME,"rb+") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(VALUE)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{VALUE}'"  
> &nbsp;&nbsp;}
> 
> &nbsp;&nbsp;# "rb" for reading the data  
> &nbsp;&nbsp;File.open(FNAME,"rb") {|fd|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;patched=fd.read(VALUE.length)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "read modified piece of data = '#{patched}'"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Oooops !!!" unless VALUE==patched  
> &nbsp;&nbsp;}
> 
> Regards,  
> Pit
> 
> [1] [class IO - RDoc Documentation](http://www.ruby-doc.org/core/classes/IO.html)

Hi Pit,  
thanks for your contribution.  
That's exactly the solution I already have. What I dont like about this solution is that you have to open and close file descriptors 3 times just for patching one little file (For sure a working solution but quite some overhead). Just for academical reason it seeems I have to fall back reading the C-sources ☹ to find out what is going wrong under the hood.

Chris

---

<div class="post-metadata">

### Author: ![Chris\_Gunther](https://avatars.discourse-cdn.com/v4/letter/c/4da419/32.png) [@Chris\_Gunther](https://rubytalk.org/u/Chris_Gunther)
#### Post date: [23 March 2005 16:54 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/11 "2005-03-23T16:54:51Z")

</div>

Carlos wrote:

> [Chris Günther \<cg\_@gmx.de\>, 2005-03-22 12.29 CET]
> 
> > Thanks Robert,
> > 
> > you are absolutely right with your remarks using a block. The code I posted was just a small copied fraction of the real code, in which I cannor use a block because the same fd will be stored in a hash for later usage by another method.  
> > Anyway, meanwhile I found the cause of this problem (again you are right, it was not in the code I posted) , but now I have another related problem that tricks my mind. I am trying to patch binary data in a file.  
> > Unfortunately the data I am patching is not the data I get when reading it back from the patched binary file.  
> > Any ideas??
> 
> All your problems come from the fact that your are opening the file for  
> appending ("ab+") instead of for reading ("r+b"). With "ab+", you can set fd.pos=0,  
> if you want, but it will always write at the end of file.

Ok, I got it - (maybe only for me) this kind of semanctics is really confusing (and not well described either).

Anyway thanks a lot,  
Chris

---

<div class="post-metadata">

### Author: ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)
#### Post date: [23 March 2005 09:09 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/12 "2005-03-23T09:09:52Z")

</div>

"Chris Günther" \<cg\_@gmx.de\> schrieb im Newsbeitrag  
news:42405416.5050603@gmx.de...

\<snip/\>

> I dont see your point. I have to truncate after every write to ensure  
> the file size does not change. Where is the connection to the problem  
> that the read value does not match the written value ?

I don't see the point either. :-} Sorry for the confusion, I overlooked  
that you used the other form of truncate with a length.

Regards

&nbsp;&nbsp;&nbsp;&nbsp;robert

---

<div class="post-metadata">

### Author: ![Pit](https://avatars.discourse-cdn.com/v4/letter/p/f14d63/32.png) [@Pit](https://rubytalk.org/u/Pit)
#### Post date: [23 March 2005 17:30 UTC](https://rubytalk.org/t/reading-and-writing-a-binary-file/17074/13 "2005-03-23T17:30:03Z")

</div>

Chris Günther schrieb:

> That's exactly the solution I already have. What I dont like about this solution is that you have to open and close file descriptors 3 times just for patching one little file (For sure a working solution but quite some overhead).

In order to patch an existing file, all you have to do is

> > &nbsp;&nbsp;File.open(FNAME,"rb+") {|fd|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.pos=OFFSET  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd.write(VALUE)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "written modified piece of data = '#{VALUE}'"  
> > &nbsp;&nbsp;}

The other File.open calls are for creating the test file and for testing the contents of the patched file. I copied them from your initial script. Of course you could do all three steps (create, patch, test) in a single File.open block.

Regards,  
Pit
