Again, I/O between C/C++ and Java

Discussion in 'Java' started by RC, Aug 30, 2007.

  1. RC

    RC Guest

    This is continuation for my August 24th posted

    "How to convert int/float etc into byte[]?"

    float f = -10.2;

    Here is a C/C++

    // write 1 byte of float to the file pointer
    fwrite((char *)f, sizeof(float), 1, fp);

    In Java, if I used DataOutputStream class

    dataOutputStream.writeFloat(f);

    But when I compared the content of two
    binary files (C/C++ and Java) by command

    "od -a binFile"
    or
    "od -c binFile"


    The output binary file written by Java is
    different from the one written by C/C++

    Then I tried different way:

    byte[] byteArrays = (Float.toString(f)).getBytes();
    dataOutputStream.write(byteArrays, 0, byteArray.length);


    This time the binary becomes ASCII as "-10.2"

    Then, I tried one more way:

    byte[] byteArray = new byte[1];
    byte b = (Float.valueOf(f)).byteValue();
    byteArray[0] = b;
    dataOutputStream.write(byteArrays, 0, byteArray.length);


    But still no luck, the output binary file in Java
    is still not the same as one in C/C++.

    So back to my original question, what is the correct
    way to convert a float, int, double, short, long, etc.
    into a byte array?

    Thank Q very much!
     
    RC, Aug 30, 2007
    #1
    1. Advertising

  2. On Aug 30, 8:54 pm, RC <> wrote:
    > So back to my original question, what is the correct
    > way to convert a float, int, double, short, long, etc.
    > into a byte array?


    The correct way is to first specify the format you want to have in the
    file in an non-ambiguous way. Then you implement the specification in
    both languages.

    Just because C can be used to dump the contents of a memory region 1:1
    to a file doesn't mean you have a format specification of any kind.
     
    Hunter Gratzner, Aug 30, 2007
    #2
    1. Advertising

  3. RC

    RC Guest

    Hunter Gratzner wrote:
    > On Aug 30, 8:54 pm, RC <> wrote:
    >> So back to my original question, what is the correct
    >> way to convert a float, int, double, short, long, etc.
    >> into a byte array?

    >
    > The correct way is to first specify the format you want to have in the
    > file in an non-ambiguous way. Then you implement the specification in
    > both languages.
    >


    I agree with you. I prefer use format fprintf(fp, "%5.1f", f); in C/C++

    But that C program was written by other programmer, he/she used
    fwrite function without format. That binary file written by
    C is read by another C program.

    Now I have to write in Java produce the same binary file for that
    program to read. That binary file should be able read by Java, C/C++
    program.

    > Just because C can be used to dump the contents of a memory region 1:1
    > to a file doesn't mean you have a format specification of any kind.
    >
     
    RC, Aug 30, 2007
    #3
  4. RC wrote:
    > But that C program was written by other programmer, he/she used
    > fwrite function without format. That binary file written by
    > C is read by another C program.
    >
    > Now I have to write in Java produce the same binary file for that
    > program to read. That binary file should be able read by Java, C/C++
    > program.


    Have you looked at the bit/byte patterns using "od -tx1" to see if the
    difference is something obvious? Like big-vs-little endian?
    (C/C++ will dump the value in whatever the native order is
    while I would expect [without testing, mind you!] Java to use
    a standard representation regardless of the native byte ordering.
    Try dumping a 4-byte integer both ways and compare to see if
    the byte-ordering is an issue.

    --
    Steve Wampler --
    The gods that smiled on your birth are now laughing out loud.
     
    Steve Wampler, Aug 30, 2007
    #4
  5. RC wrote:
    > Hunter Gratzner wrote:
    >> On Aug 30, 8:54 pm, RC <> wrote:
    >>> So back to my original question, what is the correct
    >>> way to convert a float, int, double, short, long, etc.
    >>> into a byte array?

    >>
    >> The correct way is to first specify the format you want to have in the
    >> file in an non-ambiguous way. Then you implement the specification in
    >> both languages.
    >>

    >
    > I agree with you. I prefer use format fprintf(fp, "%5.1f", f); in C/C++


    A file can have a known, defined format without being a text file. A
    format specification can say things like "32 bit binary integer, 2's
    complement, little endian byte order.".

    > But that C program was written by other programmer, he/she used
    > fwrite function without format. That binary file written by
    > C is read by another C program.
    >
    > Now I have to write in Java produce the same binary file for that
    > program to read. That binary file should be able read by Java, C/C++
    > program.


    You still need to beg, borrow, steal or create a file format
    specification. If you know the system and implementation of C++ on which
    the program was created, as well as the C struct definition, you should
    be able to find out the format.

    If you have access to any C++ programmer who is familiar with the system
    and C++ implementation they should be able to tell you the mapping from
    C++ struct to file format.

    I suspect that if you posted the information about the C++ environment
    and the struct, someone here could give you some tips. As it is, I have
    no idea of some of the most basic information about your file.

    Patricia
     
    Patricia Shanahan, Aug 30, 2007
    #5
  6. RC

    Guest

    On Aug 30, 9:22 pm, RC <> wrote:
    > But that C program was written by other programmer, he/she used
    > fwrite function without format. That binary file written by
    > C is read by another C program.


    --->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->
    %---
    From: "Paul Lutus" <>
    Newsgroups: gnu.gcc.help,gnu.g+
    +.help,comp.unix.programmer,comp.unix.solaris,comp.lang.c )

    Subject: Re: HELP: struct data members alignment???
    Date: 07 Jun 1999 00:00:00 GMT

    About this subject, and in seemingly endless threads, we get two kinds
    of
    posts:

    1. Why can't I just write raw structure data to a file or network
    socket?
    Writing it as text or packaging it in a portable, binary form is a lot
    of
    work, and I probably won't be moving the program to a different
    platform
    anyway.

    2. How come my program on platform B cannot read the raw structure
    data from
    platform A?

    The answer to (1) is (2). The answer to (2) is (1).

    --

    Paul Lutus
    www.arachnoid.com
    --->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->%--->
    %---

    Source: http://www.rdrop.com/~cary/html/endian_faq.html
     
    , Aug 30, 2007
    #6
  7. RC

    Lew Guest

    RC wrote:
    >>>> So back to my original question, what is the correct
    >>>> way to convert a float, int, double, short, long, etc.
    >>>> into a byte array?


    Hunter Gratzner wrote:
    >>> The correct way is to first specify the format you want to have in the
    >>> file in an non-ambiguous way. Then you implement the specification in
    >>> both languages.


    Patricia Shanahan wrote:
    > You still need to beg, borrow, steal or create a file format
    > specification. If you know the system and implementation of C++ on which
    > the program was created, as well as the C struct definition, you should
    > be able to find out the format.


    By my count, this is at least four times you've received this same answer, RC.

    It was explained that Java emits big-endian values, and C++ on many platforms
    (not all) emits little-endian. It was explained that C++ binary file formats
    vary according to the compiler options and other aspects of the C++
    environment. It was explained that you need to know which format applies in
    your specific case in order to get Java to emit the same data. Converting
    float to byte doesn't do it, because Java performs a value conversion rather
    than a bitwise mapping to do that. Simply writing arbitrary file formats
    doesn't work, as you've discovered, because you are not controlling your IO to
    match what the C++ program does. Indeed, you have yet to analyze what the C++
    program does, an essential first step.

    So instead of asking the question again to get the same answer, ascertain what
    the C++ file format is. Then use one of the tricks provided to you by people
    here to get Java to write the exact same format.

    --
    Lew
     
    Lew, Aug 30, 2007
    #7
  8. Patricia Shanahan wrote:
    > RC wrote:
    >> Hunter Gratzner wrote:
    >>> On Aug 30, 8:54 pm, RC <> wrote:
    >>>> So back to my original question, what is the correct
    >>>> way to convert a float, int, double, short, long, etc.
    >>>> into a byte array?

    ....
    > A file can have a known, defined format without being a text file. A
    > format specification can say things like "32 bit binary integer, 2's
    > complement, little endian byte order.".


    Nicely put. To expand just a bit...

    In RC's case, it has a known defined order that will vary depending
    upon the architecture the C program is run on. The C code he gave
    for writing the float is very specific to the native architecture.
    Changing that architecture (by going from x86 to SPARC, say) will
    change the output. So it's probably safe to assume that Patricia
    is spot on with the caveat that the format can probably be determined
    by simple inspection using 'od'.

    Since the Java program is constrained to produce the exact same
    format that is currently produced, it suffices to determine that
    native order and cobble some code to force that order. One
    particularly ugly approach would be to use Float.floatToIntBits(f)
    and then use shifting and masking to extract the bytes for
    further processing.

    The nice thing about the Java version versus the (original) C/C++
    version is that the Java solution will then produce that format
    independent of the native architecture.

    --
    Steve Wampler --
    The gods that smiled on your birth are now laughing out loud.
     
    Steve Wampler, Aug 30, 2007
    #8
  9. Steve Wampler wrote:
    > Patricia Shanahan wrote:
    >> RC wrote:
    >>> Hunter Gratzner wrote:
    >>>> On Aug 30, 8:54 pm, RC <> wrote:
    >>>>> So back to my original question, what is the correct
    >>>>> way to convert a float, int, double, short, long, etc.
    >>>>> into a byte array?

    > ...
    >> A file can have a known, defined format without being a text file. A
    >> format specification can say things like "32 bit binary integer, 2's
    >> complement, little endian byte order.".

    >
    > Nicely put. To expand just a bit...
    >
    > In RC's case, it has a known defined order that will vary depending
    > upon the architecture the C program is run on. The C code he gave
    > for writing the float is very specific to the native architecture.
    > Changing that architecture (by going from x86 to SPARC, say) will
    > change the output. So it's probably safe to assume that Patricia
    > is spot on with the caveat that the format can probably be determined
    > by simple inspection using 'od'.


    Yes, even if I think I know how a particular compiler lays things out, I
    would at least want to check against an 'od' to see if reality matches
    my theory.

    >
    > Since the Java program is constrained to produce the exact same
    > format that is currently produced, it suffices to determine that
    > native order and cobble some code to force that order. One
    > particularly ugly approach would be to use Float.floatToIntBits(f)
    > and then use shifting and masking to extract the bytes for
    > further processing.
    >
    > The nice thing about the Java version versus the (original) C/C++
    > version is that the Java solution will then produce that format
    > independent of the native architecture.
    >


    I'm not at all sure it will be necessary to do any bit twiddling at all.
    If the file is big endian, DataOutputStream should do the job after
    working out a few details of e.g. whether there is padding and if so
    where, and which Java type to use for each field. If the file is little
    endian, then Roedy's LEDataOutputStream does the job.

    Patricia
     
    Patricia Shanahan, Aug 31, 2007
    #9
  10. RC

    ~kurt Guest

    RC <> wrote:
    >
    > But that C program was written by other programmer, he/she used
    > fwrite function without format. That binary file written by
    > C is read by another C program.


    What platform is the program that creates the file running on?

    - Kurt
     
    ~kurt, Aug 31, 2007
    #10
  11. RC

    Roedy Green Guest

    On Thu, 30 Aug 2007 14:54:41 -0400, RC <>
    wrote, quoted or indirectly quoted someone who said :

    >So back to my original question, what is the correct
    >way to convert a float, int, double, short, long, etc.
    >into a byte array?


    I repeat for the third time, there is no need for than sort of farting
    about. You can read a C++ little-endian binary file exactly as if it
    were a Java big-endian, simply by using LEDataInputStream instead of
    DataInputStream.

    See http://mindprod.com/applet/fileio.html
    for sample code.
    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
     
    Roedy Green, Sep 1, 2007
    #11
  12. RC wrote:
    > This is continuation for my August 24th posted


    > "How to convert int/float etc into byte[]?"


    > float f = -10.2;


    > Here is a C/C++


    > // write 1 byte of float to the file pointer
    > fwrite((char *)f, sizeof(float), 1, fp);


    > In Java, if I used DataOutputStream class
    >
    > dataOutputStream.writeFloat(f);


    > But when I compared the content of two
    > binary files (C/C++ and Java) by command


    > "od -a binFile"
    > or
    > "od -c binFile"


    > The output binary file written by Java is
    > different from the one written by C/C++


    It would help to diagnose the problem if you could say what the two
    actually are, and not just that they're "different".

    But if the problem is byte sex, you could use:

    dataOutputStream.writeShort(Short.reverseBytes(s))
    dataOutputStream.writeInt(Integer.reverseBytes(i))
    dataOutputStream.writeLong(Long.reverseBytes(l))
    dataOutputStream.writeInt(Integer.reverseBytes(Float.floatToIntBits(f)))
    dataOutputStream.writeLong(Long.reverseBytes(Double.doubleToLongBits(d)))

    and:

    s=Short.reverseBytes(dataInputStream.readShort())
    i=Integer.reverseBytes(dataInputStream.readInt())
    l=Long.reverseBytes(dataInputStream.readLong())
    f=Float.intBitsToFloat(Integer.reverseBytes(dataInputStream.readInt()))
    d=Double.longBitsToDouble(Long.reverseBytes(dataInputStream.readLong()))
    --
    John W. Kennedy
    "Never try to take over the international economy based on a radical
    feminist agenda if you're not sure your leader isn't a transvestite."
    -- David Misch: "She-Spies", "While You Were Out"
     
    John W. Kennedy, Sep 1, 2007
    #12
    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. amit
    Replies:
    0
    Views:
    413
  2. che
    Replies:
    2
    Views:
    524
  3. abcd

    Importing again and again

    abcd, Jun 8, 2006, in forum: Python
    Replies:
    9
    Views:
    342
    Maric Michaud
    Jun 9, 2006
  4. Ò»Ê×Ê«

    A design problem I met again and again.

    Ò»Ê×Ê«, Apr 1, 2009, in forum: Python
    Replies:
    24
    Views:
    758
    Dennis Lee Bieber
    Apr 4, 2009
  5. Alexander Burger

    jsf 2.0 datatable reload again and again

    Alexander Burger, Sep 23, 2010, in forum: Java
    Replies:
    14
    Views:
    4,426
    Arved Sandstrom
    Sep 26, 2010
Loading...

Share This Page