binary data conversion

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Drake

    #1

    binary data conversion

    Well, I'm stuck in legacy land and I need a helping hand.

    We're trying to give some modern value-added functionality to
    a circa-1985 fortran proggie.

    The program produces a binary file, by itself no problem...
    each record needs to be converted into std::vector<mys truct>
    I'm having a helluva time with the binary-->(pod)datatyp e conversion.

    Although I've referred to C++ containers, iostreams
    are not used... FILE* only. Insert/extract operators are not an option.

    Here's 3 records (broken into lines for easy reading)...

    D5840000428F000 0140501000B0000 000000
    993A000066C7000 0140501000F0000 000000
    C0880000538D010 0140501001D0000 000000

    Here's (pod) mystruct...

    static struct IDX_RECORD /* length 18 bytes */
    {
    unsigned long respnum; // 4 bytes
    unsigned long datfile_offset; // 4 bytes
    unsigned char disposition; // 1 byte
    unsigned char status; // 1 byte
    unsigned char segment_svd; // 1 byte
    unsigned char not_used; // 1 byte
    unsigned short segment_dupr; // 2 bytes
    unsigned long next_segment_of fset; // 4 bytes
    };

    Is this one of those times fscanf IS the "better" (whatever that means) way?

    Assuming the powers have big-time aversion to "scan" functions,
    what's an alternative?

    Thank you for your thoughts,
    Drake
  • Martin Ambuhl

    #2
    Re: binary data conversion

    Drake wrote:
    [color=blue]
    > Well, I'm stuck in legacy land and I need a helping hand.
    >
    > We're trying to give some modern value-added functionality to
    > a circa-1985 fortran proggie.
    >
    > The program produces a binary file, by itself no problem...
    > each record needs to be converted into std::vector<mys truct>[/color]

    Bummer. Ask C++ questions in a C++ newsgroup like news:comp.lang. c++

    Comment

    • Mike Wahler

      #3
      Re: binary data conversion


      "Drake" <x@y.net> wrote in message
      news:Xns94C7AF6 EC57AEnomailcom @207.217.125.20 4...[color=blue]
      > Well, I'm stuck in legacy land and I need a helping hand.
      >
      > We're trying to give some modern value-added functionality to
      > a circa-1985 fortran proggie.
      >
      > The program produces a binary file, by itself no problem...
      > each record needs to be converted into std::vector<mys truct>
      > I'm having a helluva time with the binary-->(pod)datatyp e conversion.
      >
      > Although I've referred to C++ containers, iostreams
      > are not used... FILE* only. Insert/extract operators are not an option.
      >
      > Here's 3 records (broken into lines for easy reading)...
      >
      > D5840000428F000 0140501000B0000 000000
      > 993A000066C7000 0140501000F0000 000000
      > C0880000538D010 0140501001D0000 000000
      >
      > Here's (pod) mystruct...
      >
      > static struct IDX_RECORD /* length 18 bytes */
      > {
      > unsigned long respnum; // 4 bytes
      > unsigned long datfile_offset; // 4 bytes
      > unsigned char disposition; // 1 byte
      > unsigned char status; // 1 byte
      > unsigned char segment_svd; // 1 byte
      > unsigned char not_used; // 1 byte
      > unsigned short segment_dupr; // 2 bytes
      > unsigned long next_segment_of fset; // 4 bytes
      > };[/color]

      I'll assume those byte sizes in your comments refer
      to your particular implementation. The language
      doesn't require those sizes (but it does require
      minimum sizes).
      [color=blue]
      >
      > Is this one of those times fscanf IS the "better" (whatever that means)[/color]
      way?[color=blue]
      >
      > Assuming the powers have big-time aversion to "scan" functions,
      > what's an alternative?[/color]

      fscanf() is not what you need. It reads textual data.

      Use fread(). And be sure to account for 'endianness'.

      -Mike


      Comment

      • Mac

        #4
        Re: binary data conversion

        On Sun, 11 Apr 2004 00:14:44 +0000, Drake wrote:
        [color=blue]
        > Well, I'm stuck in legacy land and I need a helping hand.
        >
        > We're trying to give some modern value-added functionality to
        > a circa-1985 fortran proggie.
        >
        > The program produces a binary file, by itself no problem...
        > each record needs to be converted into std::vector<mys truct>
        > I'm having a helluva time with the binary-->(pod)datatyp e conversion.
        >
        > Although I've referred to C++ containers, iostreams
        > are not used... FILE* only. Insert/extract operators are not an option.
        >
        > Here's 3 records (broken into lines for easy reading)...
        >
        > D5840000428F000 0140501000B0000 000000
        > 993A000066C7000 0140501000F0000 000000
        > C0880000538D010 0140501001D0000 000000[/color]

        Is this a hex dump of the file, or is the file text... You said it was
        binary earlier.
        [color=blue]
        >
        > Here's (pod) mystruct...
        >
        > static struct IDX_RECORD /* length 18 bytes */
        > {
        > unsigned long respnum; // 4 bytes
        > unsigned long datfile_offset; // 4 bytes
        > unsigned char disposition; // 1 byte
        > unsigned char status; // 1 byte
        > unsigned char segment_svd; // 1 byte
        > unsigned char not_used; // 1 byte
        > unsigned short segment_dupr; // 2 bytes
        > unsigned long next_segment_of fset; // 4 bytes
        > };
        >
        > Is this one of those times fscanf IS the "better" (whatever that means) way?
        >[/color]

        Well, if the file is text, I think fscanf() is probably the best way, but
        you can do whatever you want, including reading a character at a time with
        getc() and not calling any other library functions. Another function to
        consider is fgets() (again, assuming a text file.)

        If the file is binary, which is what you said initially, I definitely
        would not use fscanf(). I would use getc() or fread().
        [color=blue]
        > Assuming the powers have big-time aversion to "scan" functions,
        > what's an alternative?
        >[/color]

        What do you mean by "powers?" Is that short for "powers that be," meaning,
        loosely, whoever is in charge?
        [color=blue]
        > Thank you for your thoughts,
        > Drake[/color]


        I think you may want comp.lang.c++.

        If you want a c solution, I suggest you rephrase to make that more clear,
        removing all reference to c++, just to be safe, and repost.

        If you want a c++ solution, post in comp.lang.c++, but read their faq
        and/or lurk first to make sure you don't annoy anyone.

        --Mac

        Comment

        • Drake

          #5
          Re: binary data conversion

          Martin Ambuhl <mambuhl@earthl ink.net> wrote in news:c5a47k$2m9 rj0$3@ID-
          227552.news.uni-berlin.de:
          [color=blue]
          > Drake wrote:
          >[color=green]
          >> Well, I'm stuck in legacy land and I need a helping hand.
          >>
          >> We're trying to give some modern value-added functionality to
          >> a circa-1985 fortran proggie.
          >>
          >> The program produces a binary file, by itself no problem...
          >> each record needs to be converted into std::vector<mys truct>[/color]
          >
          > Bummer. Ask C++ questions in a C++ newsgroup like news:comp.lang. c++[/color]


          A few lines later the post tried and obviously failed in avoiding this
          answer.

          << Although I've referred to C++ containers, iostreams
          << are not used... FILE* only. Insert/extract operators are not an
          << option.

          Anyway std::vector isn't the problem. It's the conversion.


          Drake

          Comment

          • Dilton McGowan II

            #6
            Re: binary data conversion

            "Drake" <x@.y.net> wrote in message
            news:Ju3ec.4494 $k05.1243@newsr ead2.news.pas.e arthlink.net...[color=blue]
            > Martin Ambuhl <mambuhl@earthl ink.net> wrote in news:c5a47k$2m9 rj0$3@ID-
            > 227552.news.uni-berlin.de:
            >[color=green]
            > > Drake wrote:
            > >[color=darkred]
            > >> Well, I'm stuck in legacy land and I need a helping hand.
            > >>
            > >> We're trying to give some modern value-added functionality to
            > >> a circa-1985 fortran proggie.
            > >>
            > >> The program produces a binary file, by itself no problem...
            > >> each record needs to be converted into std::vector<mys truct>[/color]
            > >
            > > Bummer. Ask C++ questions in a C++ newsgroup like news:comp.lang. c++[/color]
            >
            >
            > A few lines later the post tried and obviously failed in avoiding this
            > answer.
            >
            > << Although I've referred to C++ containers, iostreams
            > << are not used... FILE* only. Insert/extract operators are not an
            > << option.
            >
            > Anyway std::vector isn't the problem. It's the conversion.
            >
            >
            > Drake[/color]

            Tastefully dispatched. ;-)

            Comment

            • Malcolm

              #7
              Re: binary data conversion


              "Drake" <x@y.net> wrote in message[color=blue]
              >
              > Here's 3 records (broken into lines for easy reading)...
              >
              > D5840000428F000 0140501000B0000 000000
              > 993A000066C7000 0140501000F0000 000000
              > C0880000538D010 0140501001D0000 000000
              >
              > Here's (pod) mystruct...
              >
              > static struct IDX_RECORD /* length 18 bytes */
              > {
              > unsigned long respnum; // 4 bytes
              > unsigned long datfile_offset; // 4 bytes
              > unsigned char disposition; // 1 byte
              > unsigned char status; // 1 byte
              > unsigned char segment_svd; // 1 byte
              > unsigned char not_used; // 1 byte
              > unsigned short segment_dupr; // 2 bytes
              > unsigned long next_segment_of fset; // 4 bytes
              > };
              >
              > Assuming the powers have big-time aversion to "scan" functions,
              > what's an alternative?
              >[/color]
              As someone else has pointed out, you don't say whether your example is a
              hexdump or a text file. fscanf() is useful only for text files, but of
              limited utlity if numerics are not separated by delimiters.

              What you need are the functions

              unsigned long read32us(FILE *fp);
              unsigned short read16us(FILE *fp);

              If you want to use C++ you can be ugly and replace the FILE * with a stream,
              or be object-oriented and derive a class from iostream with the functions
              added.
              In either case, build the read32() function on top of fgetc() / character
              extraction.
              If you are using C++, throw exceptions in the case of premature EOF.


              Comment

              • Thomas Matthews

                #8
                Re: binary data conversion

                Drake wrote:
                [color=blue]
                > Well, I'm stuck in legacy land and I need a helping hand.
                >
                > We're trying to give some modern value-added functionality to
                > a circa-1985 fortran proggie.
                >
                > The program produces a binary file, by itself no problem...
                > each record needs to be converted into std::vector<mys truct>
                > I'm having a helluva time with the binary-->(pod)datatyp e conversion.
                >
                > Although I've referred to C++ containers, iostreams
                > are not used... FILE* only. Insert/extract operators are not an option.
                >
                > Here's 3 records (broken into lines for easy reading)...
                >
                > D5840000428F000 0140501000B0000 000000
                > 993A000066C7000 0140501000F0000 000000
                > C0880000538D010 0140501001D0000 000000
                >
                > Here's (pod) mystruct...
                >
                > static struct IDX_RECORD /* length 18 bytes */
                > {
                > unsigned long respnum; // 4 bytes
                > unsigned long datfile_offset; // 4 bytes
                > unsigned char disposition; // 1 byte
                > unsigned char status; // 1 byte
                > unsigned char segment_svd; // 1 byte
                > unsigned char not_used; // 1 byte
                > unsigned short segment_dupr; // 2 bytes
                > unsigned long next_segment_of fset; // 4 bytes
                > };
                >
                > Is this one of those times fscanf IS the "better" (whatever that means) way?
                >
                > Assuming the powers have big-time aversion to "scan" functions,
                > what's an alternative?
                >
                > Thank you for your thoughts,
                > Drake[/color]

                If your file is ASCII encoded hex file (a.k.a. Hex dump),
                then you may want to read each line using fgets(), then
                fill in your data structure by converting the ASCII values
                into native formats. This is probably the faster method
                than fscanf.

                If the file is actually binary, you may want to use the
                fread function and read a block into a buffer then load
                the fields of your structure from the buffer.

                In no case do you want to load your structure directly
                from the file or memory. The simple rule is that the
                size of a structure may not be equal to the size of its
                members. The compiler is allowed to add "padding" bytes
                between members. This is what kills most programs that
                attempt to map a structure directly to an input stream.


                --
                Thomas Matthews

                C++ newsgroup welcome message:

                C++ Faq: http://www.parashift.com/c++-faq-lite
                C Faq: http://www.eskimo.com/~scs/c-faq/top.html
                alt.comp.lang.l earn.c-c++ faq:

                Other sites:
                http://www.josuttis.com -- C++ STL Library book

                Comment

                Working...