octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Is there a better way to fwrite()?


From: Daniel J Sebald
Subject: Is there a better way to fwrite()?
Date: Fri, 27 Jan 2006 23:46:17 -0600
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020

I'm going to lobby a bit here for a change of behavior in "fwrite", illustrated 
by the following example:

Say I want to write to a binary file tuples of numbers, oh 10 unit8's and 2 
float32's.  I want to do this efficiently, rather than using some kind of loop. 
 Well, let's think of how to do that with fwrite().  One's inclination would be 
to use skip and multiple applications of fwrite in some way.  Try this:

fid = fopen('test.bin', 'w+');
X = [ones(10); rand(2,10)];
here = ftell(fid);
fseek(fid, here, 'bof');
fwrite(fid, X(1:10,:), '10*uint8', 8);
fclose(fid);

as just a means to get started.  Similar to fread, one might think, hey this will write 
10 uint8's then skip the space for the two float32's.  However, we see that "there 
is nothing to skip" because there isn't yet any data at the end of the file to skip. 
 So this actually turns out to be only 100 bytes.  [use hexedit to observe the file.]  I 
argue that it would be nice for fwrite() to place some bytes of 0 in there, but I'll come 
back to that.  I don't show the remaining commands for writing the two float32's.  It 
obviously won't work.

Let's move on.  OK, how about this:

fid = fopen('test.bin', 'w+');
X = [ones(10); rand(2,10)];
here = ftell(fid);
fwrite(fid, zeros(18,10), 'char');
fseek(fid, here - 8, 'bof');
fwrite(fid, X(1:10,:), '10*uint8', 8);
fseek(fid, here, 'bof');
fwrite(fid, X(11:12,:), '2*float32', 10);
fclose(fid);

The "here - 8" is because fwrite() "pre-skips" as opposed to "post-skips" as 
does fread().  Slightly confusing, but workable, accept for one thing in this case.  If here equals 0, here - 
8 seems to be undefined as far as a file pointer.  If one looks at the results using hexedit, the 1's appear 
way at the end of the file.  But the thing to note here is the inconvenient write of an equal amount of zeros 
first.  It's like writing the data twice.

And here is the final correct code that gets what I want:

fid = fopen('test.bin', 'w+');
X = [ones(10); rand(2,10)];
here = ftell(fid);
fwrite(fid, zeros(18,10), 'char');
fseek(fid, here, 'bof');
fwrite(fid, X(1:10,1), '10*uint8');
fwrite(fid, X(1:10,2:10), '10*uint8', 8);
fseek(fid, here, 'bof');
fwrite(fid, X(11:12,:), '2*float32', 10);
fclose(fid);

So, questions:

1) Why can't a negative number be a valid file pointer so that the pre-skip of 
fwrite() would work correctly with

fid = fopen('test.bin', 'w+');
X = [ones(10); rand(2,10)];
here = ftell(fid);
fwrite(fid, zeros(18,10), 'char');
fseek(fid, here - 8, 'bof');
fwrite(fid, X(1:10,:), '10*uint8', 8);
fseek(fid, here, 'bof');
fwrite(fid, X(11:12,:), '2*float32', 10);
fclose(fid);

and avoid an extra command?

2) Why can't fwrite() put zeros in place of the "skipped" bytes at the end of 
the file if they do not exist?  That way I could use

fid = fopen('test.bin', 'w+');
X = [ones(10); rand(2,10)];
here = ftell(fid);
fseek(fid, here - 8, 'bof');
fwrite(fid, X(1:10,:), '10*uint8', 8);
fseek(fid, here, 'bof');
fwrite(fid, X(11:12,:), '2*float32', 10);
fclose(fid);

and avoid having to write the same amount of data twice.  I understand the 
logic why not--there is nothing at the end of the file to skip.  But as it is 
right now with a file empty at the end, the following are essentially the same:

fwrite(fid, X(1:10,:), '10*uint8', 8);
fwrite(fid, X(1:10,:), '10*uint8');

Surely, one wouldn't expect those to have the same behavior.  I.e., no one 
would choose the first in the expectation that it will behave like the second, 
whould they?

Dan

PS:  fwrite(fid, X, '10*uint8,2*float32') would be the nicest solution, but 
that doesn't seem to work and probably isn't the way things are defined.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]