Reading a Binary File....

Discussion in 'C Programming' started by swetha, Nov 19, 2007.

  1. swetha

    swetha Guest

    HI Every1,
    I have a problem in reading a binary file.
    Actually i want a C program which reads in the data from a file which
    is in binary format and i want to update values in it.
    The file consists of structures of type----

    struct record {
    int acountnum;
    char name[20];
    float value;
    char phone[10];
    }

    I wrote a program which reads in these values into a structure which i
    created in my program.While printing the values i got the "name" and
    "phone" values correctly ( as they are in char) ....but iam not
    getting the accountnum and value fields.Iam getting some arbitary
    values.SO can any1 help me out in this of how to retrieve the values
    correctly ......

    My code is...

    struct record{
    int acctnum;
    char name[20];
    float value;
    char phone[10];
    int age;
    };

    struct record data;
    FILE *file = fopen("db07", "rb");
    while ( fread(&data, sizeof (struct record), 1, file) == 1 )
    {
    printf("Name:%s\nAccount Number :%d\nAge:%d\nPhone:%s\nValue:%f\n",
    data.name, data.acctnum,data.age,data.phone,data.value);
    }
     
    swetha, Nov 19, 2007
    #1
    1. Advertisements

  2. swetha

    John Gordon Guest

    Was the original datafile created on a different computer?
     
    John Gordon, Nov 19, 2007
    #2
    1. Advertisements

  3. [OP's code is at EOM]

    /* You don't indicate how these files are created. In the example
    * below I have added the writing of these files. Note that the
    * structures in your file are not the same as those that you are using
    * in your program. Also note that for 10-digit phone numbers (or
    * 20-character names) your members name and phone are not strings,
    * since they are not null terminated */

    #include <stdio.h>
    #include <stdlib.h>

    struct file_record
    {
    int acountnum;
    char name[20];
    float value;
    char phone[10];
    };

    struct internal_record
    {
    int acctnum;
    char name[20];
    float value;
    char phone[10];
    int age;
    };

    void show_char_array(const char *label, size_t n, const char *s)
    {
    size_t i;
    printf("%s:", label);
    for (i = 0; i < n && s; i++)
    putchar(s);
    putchar('\n');
    }

    int main(void)
    {
    struct file_record make[3] = {
    {1, "first guy", 72.3, "3123375032"},
    {2, "second guy", 333.72, "2128836234"},
    {3, "third guy", -62, "6182213"}
    };
    struct internal_record data;
    FILE *file;
    size_t written;

    if (!(file = fopen("db07", "wb"))) {
    fprintf(stderr, "could not open output file\n");
    exit(EXIT_FAILURE);
    }
    written = fwrite(&make, sizeof *make, 3, file);
    printf("%zu records written.\n", written);
    fclose(file);

    if (!(file = fopen("db07", "rb"))) {
    fprintf(stderr, "could not open input file\n");
    exit(EXIT_FAILURE);
    }
    printf("Note that the age member is not present in the input.\n"
    "I have set it at 26\n\n");
    data.age = 26;
    while (fread(&data, sizeof *make, 1, file)) {
    show_char_array("Name", 20, data.name);
    printf("Account Number :%d\nAge:%d\n", data.acctnum, data.age);
    show_char_array("Phone", 10, data.phone);
    printf("Value:%f\n\n", data.value);
    }
    fclose(file);
    remove("db07");
    return 0;
    }

    [Output]
    3 records written.
    Note that the age member is not present in the input.
    I have set it at 26

    Name:first guy
    Account Number :1
    Age:26
    Phone:3123375032
    Value:72.300003

    Name:second guy
    Account Number :2
    Age:26
    Phone:2128836234
    Value:333.720001

    Name:third guy
    Account Number :3
    Age:26
    Phone:6182213
    Value:-62.000000


    [OP's code]
     
    Martin Ambuhl, Nov 19, 2007
    #3
  4. swetha

    Eric Sosman Guest

    swetha wrote On 11/19/07 16:24,:
    Any of several things -- or a combination -- could be
    the problem. Here are a few areas you should probably take
    a look at:

    1) Why does your program try to read an "age" element
    that's not mentioned in your description of the file format?
    If you read into a struct whose layout doesn't match that of
    the file, you can't expect anything useful to happen.

    2) Was the file written on a system compatible with the
    one that's trying to read it? Systems differ in many ways,
    such as the way numbers (int, float) are represented, the
    amount and placement of padding within structs, and so on.
    Padding differences would produce problems like those of (1),
    and representation differences (e.g., "endianness") can be
    even thornier: Something that means 123 to one machine might
    easily mean -2231369728 to another.

    3) The "name" and "phone" elements: Are all 20 or 10
    characters actually present in the file, even if the strings
    are as short as "Zaphod" and "n/a"? Or does the file hold
    only the "significant" characters? (And see Martin Ambuhl's
    warning about the possible non-string-ness of these items.)

    A hex dump of the first couple hundred bytes of the file,
    along with what they're "supposed to" represent and what you
    actually get from your program, might be helpful.
     
    Eric Sosman, Nov 19, 2007
    #4
  5. swetha

    swetha Guest



    Hi.....actually i have forgot age in the previous structre...age is
    present in both....and there is no need to put data into that
    file.....already i have a file which consists of data in the binary
    format.....i wanted to read that data ...while doing so i could easily
    i could retrieve the char values correctly but i have a problem with
    the float and int values .....for float and int what should i do ???
    i dont have any idea wher that file is from ..is ther a way to know
    that ???
     
    swetha, Nov 19, 2007
    #5
  6. You need to look at the data and see what format it is in. A hex dump
    program like od or hd (on *nix systems) will show you exactly what is
    in the file. There are so many possible formats that guessing is
    probably pointless. Posting a small extract in hex somewhere topical
    (maybe comp.programming) might help.
     
    Ben Bacarisse, Nov 20, 2007
    #6
  7. swetha

    santosh Guest

    If this file has been created on a different system to the one in which
    it is being read, or if a different program has created it than the one
    doing the reading, or if your program does not know the exact details
    of the file's format, subtle errors may occur.

    This is why it is often better to deal with text files unless there are
    compelling reasons for doing otherwise. For many programs on modern
    desktop systems, which need not be performance critical, it is just
    fine to store data in text files.
    You are missing a semi-colon to terminate the structure declaration.
    Please copy and paste code. Retyping has been proven, time and again,
    to result in annoying typos and incomplete code.
    Which structure is the one you are actually using? This one or the one
    previous? This once again illustrates why code should be, wherever
    possible, cut and pasted.
    You might use a name other than 'file' for readability reasons. Have two
    identifiers differring only in case, though legal in C, is not a very
    good programming practise. And it might lead to conflicts if the
    identifiers happen to have external linkage _and_ you happen to use a
    very old or primitive linker. Better to be safe and avoid the
    possibility altogether.
    A likely possibility is that the data file was created on a system other
    than the one it is under now, or that it was created by a program
    compiled with certain compiler options that this program (i.e., the one
    reading the file) has not taken into account.

    If it is indeed one of these possibilities then you need to know the
    exact layout of the file's structure objects before you can read it in
    correctly.
     
    santosh, Nov 20, 2007
    #7
  8. You've shown us two different struct declaration. (Is it spelled
    "acountnum" or "acctnum"? Is there an "age" member or not? We don't
    care one way or the other, but you need to.) As santosh advised in
    another followup, you should *always* copy-and-paste your exact code.
    If you attempt to re-type it or summarize it, you'll inevitably
    introduce errors that will mask whatever your real problem is. Don't
    make us waste our time correcting your typos rather than helping you
    with your actual code.

    Reading binary files is tricky, since binary formats (sizes of types,
    representations of floating-point types, byte ordering, structure
    layout, and a bunch of other things) can vary widely from one system to
    another.

    The comp.lang.c is at <http://www.c-faq.com/>. Read section 12,
    particularly the questions containing the word "binary".

    If the file you're trying to read was written on a different system, you
    may have a lot of difficulty reading it. It may be possible to analyze
    the file using hex dumps, and figure out how to do any necessary
    translation, but it's a tough job.

    If you can guarantee that the writer and reader programs will run on the
    same or identical systems, you might be ok. But in that case the first
    thing you should do is write a separate program to write some sample
    records to a file, to make sure you can read them.

    You use the "%s" format to print the name and phone members. This only
    works if they contain proper strings with null-character ('\0')
    terminators. Is this guaranteed?

    If you can use a text format rather than binary, sharing these file
    across different systems is going to be a lot easier. Is that a
    possibility?
     
    Keith Thompson, Nov 20, 2007
    #8
  9. You should be using write to output binary values. printf converts the
    output to characters.
     
    spacecriter \(Bill C\), Nov 21, 2007
    #9
  10. swetha

    Willem Guest

    swetha wrote:
    ) I wrote a program which reads in these values into a structure which i
    ) created in my program.While printing the values i got the "name" and
    ) "phone" values correctly ( as they are in char) ....but iam not
    ) getting the accountnum and value fields.Iam getting some arbitary
    ) values.SO can any1 help me out in this of how to retrieve the values
    ) correctly ......
    )
    ) My code is...
    )
    ) struct record{
    ) int acctnum;
    ) char name[20];
    ) float value;
    ) char phone[10];
    ) int age;
    ) };
    )
    ) struct record data;
    ) FILE *file = fopen("db07", "rb");
    ) while ( fread(&data, sizeof (struct record), 1, file) == 1 )
    ) {
    ) printf("Name:%s\nAccount Number :%d\nAge:%d\nPhone:%s\nValue:%f\n",
    ) data.name, data.acctnum,data.age,data.phone,data.value);
    ) }

    In C, a struct might be padded. That is, there may be some empty space
    between, say, 'name' and 'value'. If you want maximal robustness in
    reading a file, you should be reading it element by element instead.

    Also, and presumably the cause of your problem, there could be an endianess
    issue. Can you give some examples of expected and actual values ?


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
     
    Willem, Nov 21, 2007
    #10
  11. spacecriter (Bill C) wrote:
    [...]
    You probably mean (or you *should* mean) fwrite rather than write. The
    write function is non-standard (it's defined by POSIX, not by the C
    standard).

    Both fwrite and printf are defined in terms of character output. It
    *usually* makes more sense to use fwrite for binary files and printf (or
    fputs, etc) for text files, but both will work equally well for either
    text or binary.
     
    Keith Thompson, Nov 21, 2007
    #11
  12. swetha

    Old Wolf Guest

    If you have a block of "binary data", that could contain
    null characters, then the printf family isn't a suitable
    choice for output.
     
    Old Wolf, Nov 22, 2007
    #12
  13. swetha

    CBFalconer Guest

    Why? He is simply making the output legible on other systems.
    Text is portable, binary isn't.
     
    CBFalconer, Nov 22, 2007
    #13
  14. Not if you use the "%s" format, but this:
    printf("%c", '\0');
    is well defined.

    But you're right, printf wouldn't be a *suitable* choice, even though you could
    make it work with some effort.
     
    Keith Thompson, Nov 22, 2007
    #14
  15. He is not using printf to output binary values. He is using it to
    print data (suitably converted to readable characters) that he read
    from a binary file.

    Since write is not part of the standard library, fwrite would be a
    better recommendation in this group if he wanted to output binary
    data.


    Remove del for email
     
    Barry Schwarz, Nov 22, 2007
    #15
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.