Forum: Ruby reading/writing binary problem

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Wolfgang (Guest)
on 2006-03-29 18:26
(Received via mailing list)
Hi,

I have some binary files which I need to delete some data at the
beginning of the file (to extract the raw data out of the file). I got a
matlab file from a colleque but I would prefer if I could do it with
ruby.

This matlab code does the trick:
	function m=write_rad(filename)
	file=fopen(filename);
	f= fread(file,'uint16');

	[r,k]=size(f);
	if k==1;
    		t=r-1048576;
    		m=f(t+1:r,:);
	end
	end % function

How can I do this in ruby? I'm completely lost.

Thanks
Wolfgang
Robert K. (Guest)
on 2006-03-29 19:15
(Received via mailing list)
Wolfgang wrote:
>
>     [r,k]=size(f);
>     if k==1;
>            t=r-1048576;
>            m=f(t+1:r,:);
>     end
>     end % function
>
> How can I do this in ruby? I'm completely lost.

An easy solution is to copy the file:

Untested:

def cut_prefix(file, length)
   raise ArgumentError, "negative length" if length < 0

   bak = file + ".bak"
   File.rename file, bak

   File.open(bak,"rb") do |io_r|
     io_r.seek length

     File.open(file, "wb") do |io_w|
       while ( buffer = io_r.read(4096) )
         io_w.write(buffer)
       end
     end
   end
end

Another solution would be to do it internally with continuously seeking,
reading, seeking, writing etc.

Kind regards

	robert
unknown (Guest)
on 2006-03-29 19:43
(Received via mailing list)
On Wed, 29 Mar 2006, Wolfgang wrote:

>
> Wolfgang
this sould be easy if i understood that method and the nature of your
data ;-)

here's what i understand this method to do :

   # open the file

     file=fopen(filename);

   # read all available unit16 quantities into an [m, n] array

     f= fread(file,'uint16');

   # check the size of this array, r is the number of elements read

     [r,k]=size(f);

   # k will be one iff data was read into r dimension

     if k==1;

   # here i assume 1048576 is the 'row_size' of 1mb.  we set t to be the
offset
   # of the last row

     t=r-1048576;

   # because matlab is evil and uses one based indexing, we inc t by one
and
   # extract the last row/block of data.  but here it seems like the ith
index
   # should be t+1:r-1048576 no?  otherwise it seems like this would be
out of
   # bounds?

     m=f(t+1:r,:);


in any case this looks alot like you are trying to extract the last 1mb
of
uint16 quantities from a data file - is that right?  let me know and
i'll show
you how to do this.

regards.

-a
Wolfgang (Guest)
on 2006-03-29 20:16
(Received via mailing list)
Hello,

yes I want to extract a matrix of 1024x1024 of binary data (2bytes for
each value). But ahead of this data is 1048576 bit (13312 bytes) of
crap. I don't know matlab at all and I don't like to start this routine
when I want to import that data into my application, which can not skip
this header. If it is easier to do by a linux command (its running in
cygwin) any help is also welcome.

Wolfgang

PS: I will also test the example of Robert


removed_email_address@domain.invalid schrieb:
unknown (Guest)
on 2006-03-29 20:32
(Received via mailing list)
On Thu, 30 Mar 2006, Wolfgang wrote:

>
> PS: I will also test the example of Robert

ok.  so, just to clarify, you want to read a 2mb matrix out of a file
after
skiping 13312 bytes of crap.  this will do that

   def extract_data path
     open(path){|f| f.seek(13312); f.read(1024*1024*2)}
   end

here data returned is a buffer.  if you want a matrix object i
__highly__
suggest installing the narray module and using something like

   require 'narray'
   def extract_matrix path
     na = NArray.sint 1024, 1024
     open(path){|f| f.seek(13312); na[] = f.read(1024*1024*2)}
     na
   end

this will return a numerical matrix with nice operators.  you can write
it to
file with

   open('m.dat','w'){|f| f.write na}

and this will write the matix in binary.

regards.

-a
Daniel H. (Guest)
on 2006-03-29 20:41
(Received via mailing list)
On Mar 29, 2006, at 6:31 PM, removed_email_address@domain.invalid wrote:

> open(path){|f| f.seek(13312); f.read(1024*1024*2)}

If you are using Windows don't forget to open it in binary mode:

open(..., 'rb') ...

-- Daniel
Robert K. (Guest)
on 2006-03-29 20:56
(Received via mailing list)
Daniel H. wrote:
> On Mar 29, 2006, at 6:31 PM, removed_email_address@domain.invalid wrote:
>
>> open(path){|f| f.seek(13312); f.read(1024*1024*2)}
>
> If you are using Windows don't forget to open it in binary mode:
>
> open(..., 'rb') ...

In fact I recommend to use that switch regardless of OS used: it's more
portable and also serves as documentation hint that the file is actually
  binary.

Kind regards

	robert
unknown (Guest)
on 2006-03-29 20:59
(Received via mailing list)
On Thu, 30 Mar 2006, Daniel H. wrote:

> On Mar 29, 2006, at 6:31 PM, removed_email_address@domain.invalid wrote:
>
>> open(path){|f| f.seek(13312); f.read(1024*1024*2)}
>
> If you are using Windows don't forget to open it in binary mode:
>
> open(..., 'rb') ...
>
> -- Daniel

ah.  indeed.

-a
Wolfgang (Guest)
on 2006-03-29 22:15
(Received via mailing list)
Thank you all,

this worked perfectly!

Wolfgang

removed_email_address@domain.invalid schrieb:
This topic is locked and can not be replied to.