[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.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Is there a better way to fwrite()?,
Daniel J Sebald <=