Read n bytes from file

Discussion in 'C Programming' started by Alexander Hunziker, Jul 5, 2005.

  1. Hello group,

    I have a program that reads data from a binary file. I know that at some
    known position in the file there are 12 4 bytes long floating point
    numbers. Here's how I read them now:

    float temptriangle[12];

    fread(&temptriangle, 4, 12, fp);

    This works quite nicely, however it does so only if sizeof(float) is 4,
    otherwise I'll get garbage.

    Is there a cleaner way of doing it? Reading 4 bytes from a file into a
    floating point variable?

    Thanks in advance for your help,
    Alex
    Alexander Hunziker, Jul 5, 2005
    #1
    1. Advertising

  2. Alexander Hunziker

    Eric Sosman Guest

    Alexander Hunziker wrote:

    > Hello group,
    >
    > I have a program that reads data from a binary file. I know that at some
    > known position in the file there are 12 4 bytes long floating point
    > numbers. Here's how I read them now:
    >
    > float temptriangle[12];
    >
    > fread(&temptriangle, 4, 12, fp);
    >
    > This works quite nicely, however it does so only if sizeof(float) is 4,
    > otherwise I'll get garbage.
    >
    > Is there a cleaner way of doing it? Reading 4 bytes from a file into a
    > floating point variable?


    "Cleanliness is next to Godliness and next to impossible,
    too." You are aware, I hope, that different C implementations
    use different binary representation for `float', so your binary
    file may be meaningful only to the machine that wrote it. You
    have already sacrificed a certain amount of cleanliness by
    choosing to use a binary format.

    That said, the code as written can be scrubbed to a somewhat
    brighter gleam. First, get rid of the address-of `&' operator;
    see Question 6.12 in the comp.lang.c Frequently Asked Questions
    (FAQ) list <http://www.eskimo.com/~scs/C-faq/top.html> if you
    don't understand why this is the right thing to do. Second,
    you can rewrite the "magic numbers" `4' and `12' in terms of
    the `sizeof' operator. This would give something like

    fread(temptriangle, sizeof temptriangle[0],
    sizeof temptriangle / sizeof temptriangle[0], fp);

    (The third argument is correct only if `temptriangle' is an
    actual array rather than a pointer; see Question 6.21 in the FAQ.)

    Even this isn't quite as clean as it should be, because it
    lacks one important feature: it doesn't check whether fread()
    succeeded or failed. You really need something more like

    if (fread(temptriangle, ...)
    != sizeof temptriangle / sizeof temptriangle[0])
    complain_and_die();

    See the Sixth Commandment at
    <http://www.lysator.liu.se/c/ten-commandments.html>.

    --
    Eric Sosman
    lid
    Eric Sosman, Jul 5, 2005
    #2
    1. Advertising

  3. >> I have a program that reads data from a binary file. I know that at some
    >> known position in the file there are 12 4 bytes long floating point
    >> numbers. Here's how I read them now:

    >
    >Second,
    >you can rewrite the "magic numbers" `4' and `12' in terms of
    >the `sizeof' operator.


    I'll disagree here. The file format spec said it had floating point
    numbers that are *FOUR* bytes long. This is independent of the
    sizeof(float) on the target machine.

    The file format spec also said there were *TWELVE* numbers, not
    the number in any particular array. It is quite possible that
    someone might re-use the array later for a set of 17 numbers.

    Gordon L. Burditt
    Gordon Burditt, Jul 5, 2005
    #3
  4. On Tue, 05 Jul 2005 21:27:10 +0200, Alexander Hunziker wrote:

    > Hello group,
    >
    > I have a program that reads data from a binary file. I know that at some
    > known position in the file there are 12 4 bytes long floating point
    > numbers. Here's how I read them now:
    >
    > float temptriangle[12];
    >
    > fread(&temptriangle, 4, 12, fp);
    >
    > This works quite nicely, however it does so only if sizeof(float) is 4,
    > otherwise I'll get garbage.


    The question is whether you know that the format of the floating point
    values in the file corresponds to the representation used by float on your
    implementation. If it does then fine if it doesn't then clearly this won't
    work. And of sizeof(float) is not 4 then clearly the format/representation
    differs. It could differ even if sizeof(float)==4.

    > Is there a cleaner way of doing it? Reading 4 bytes from a file into a
    > floating point variable?


    To make the code general you would have to interpret the bit pattern of
    each float in the file data and build values from that.

    Lawrence
    Lawrence Kirby, Jul 6, 2005
    #4
  5. (Gordon Burditt) writes:
    >>> I have a program that reads data from a binary file. I know that at some
    >>> known position in the file there are 12 4 bytes long floating point
    >>> numbers. Here's how I read them now:

    >>
    >> Second,
    >> you can rewrite the "magic numbers" `4' and `12' in terms of
    >> the `sizeof' operator.

    >
    > I'll disagree here. The file format spec said it had floating point
    > numbers that are *FOUR* bytes long. This is independent of the
    > sizeof(float) on the target machine.
    >
    > The file format spec also said there were *TWELVE* numbers, not
    > the number in any particular array. It is quite possible that
    > someone might re-use the array later for a set of 17 numbers.


    Even so, "magic" constants are evil. Use #define and a nice block of
    comments to describe their "magic" values.

    - Giorgos
    Giorgos Keramidas, Jul 6, 2005
    #5
  6. Alexander Hunziker

    Eric Sosman Guest

    Gordon Burditt wrote:
    >>>I have a program that reads data from a binary file. I know that at some
    >>>known position in the file there are 12 4 bytes long floating point
    >>>numbers. Here's how I read them now:

    >>
    >>Second,
    >>you can rewrite the "magic numbers" `4' and `12' in terms of
    >>the `sizeof' operator.

    >
    >
    > I'll disagree here. The file format spec said it had floating point
    > numbers that are *FOUR* bytes long. This is independent of the
    > sizeof(float) on the target machine.


    That's a possible interpretation. I read the O.P. a bit
    differently, believing that when he wrote "4" he meant "the
    size of the local `float'." The example code (which you
    snipped) suggests that the file holds images of the local
    `float' and not some independently-specified format. If the
    file format *isn't* native, a lot more work is needed.

    > The file format spec also said there were *TWELVE* numbers, not
    > the number in any particular array. It is quite possible that
    > someone might re-use the array later for a set of 17 numbers.


    Yes; it's possible that "12" is non-magical. It is, after
    all, a peculiar number of values with which to describe a triangle.
    (One might even say it's an "odd" number of values ;-). Three
    points with four values each -- X,Y,Z,T? X,Y,dX/dT,dY/dT?

    --
    Eric Sosman
    lid
    Eric Sosman, Jul 6, 2005
    #6
  7. Alexander Hunziker

    Malcolm Guest

    "Alexander Hunziker" <> wrote
    > float temptriangle[12];
    >
    > fread(&temptriangle, 4, 12, fp);
    >
    > This works quite nicely, however it does so only if sizeof(float) is 4,
    > otherwise I'll get garbage.
    >
    > Is there a cleaner way of doing it? Reading 4 bytes from a file into a
    > floating point variable?
    >


    Reconstruct the floating point number from binary.

    /*
    portable read of binary float.
    Note untested guide code to show the principle only. Your exact floating
    point format may differ. */
    */
    float readfloat(FILE *fp)
    {
    unsigned char byte1;
    unsigned char byte1;
    unsigned char byte2;
    unsigned char byte3;
    int sign;
    int exponent;
    int mantissa;
    double answer;

    byte0 = fgetc(fp);
    byte1 = fgetc(fp);
    byte2 = fgetc(fp);
    byte3 = fgetc(fp);

    sign = byte0 & 0x80 ? 1 : 0;
    exponent = ((byte0 & 0x7F) << 1) + ((byte1 & 0x80) >> 7);
    mantissa = ((byte1&0x7F) << 16) + (byte2 << 8) + byte3;

    if(exponent == 0 || exponent == 0xFF)
    {
    /* these are denormalised numbers, nans, and other horrible things
    handle specially or reject. Zero you are likely to need */
    if( byte0 == 0 && byte1 == 0 && byte2 == 0 && byte3 == 0)
    return 0;
    }
    exponent -= 0x80;
    /* reconstruct the floating point number. It is in the form (1 + mantissa)
    * 2 ^ exponent */
    answer = (((double)mantissa) / 0x800000 + 1.0) * pow(2, exponent);

    if(sign)
    answer = -answer;

    return (float) answer;

    }
    Malcolm, Jul 6, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason Collins
    Replies:
    3
    Views:
    6,015
    Jason Collins
    Feb 18, 2004
  2. mrby

    4-bytes or 8-bytes alignment?

    mrby, Nov 2, 2004, in forum: C Programming
    Replies:
    8
    Views:
    419
    Mark McIntyre
    Nov 2, 2004
  3. Replies:
    5
    Views:
    547
    Flash Gordon
    Apr 9, 2006
  4. Yandos
    Replies:
    12
    Views:
    5,118
    Pete Becker
    Sep 15, 2005
  5. Replies:
    8
    Views:
    502
    Bob Hairgrove
    Apr 10, 2006
Loading...

Share This Page