float and binary write to file

This is a discussion on float and binary write to file within the C Programming forums, part of the General Programming Boards category; Hi I'd like to write files with binary content (.vtk) I need to put to file some data-points. I know ...

  1. #1
    Registered User
    Join Date
    Oct 2007
    Posts
    12

    Question float and binary write to file

    Hi
    I'd like to write files with binary content (.vtk)

    I need to put to file some data-points.
    I know that inside file should I get (I know because I compared with some other correct written .vtk files):

    3F 80 00 00 40 00 00 00

    what means points = 1 , 2

    but when I write myself :
    Code:
              float zma;	
    	  zma = 1;
    			
    	 fwrite(&zma, sizeof zma, 1, file_with_points);
    i got: >> 00 00 80 3F 00 00 00 40

    Thats big and Little Endian Byte Order problem.

    So I wrote function to change byte order.

    Code:
    signed int LE_2_BI(signed int num)
    {
    	signed int wynik = 0x00000000, maska1= 0xFF, maska2= 0xFF00, 
            maska3= 0xFF0000, maska4= 0xFF000000, 
            liczba1, liczba2, liczba3, liczba4;
    	
    				liczba1 = num & maska1;
    				liczba1 = liczba1 << 24;
    
    				liczba2 = num & maska2;
    				liczba2 = liczba2 << 8;
    		
    		 		liczba3 = num & maska3;
    				liczba3 = liczba3 >> 8;
    		
    				liczba4 = num & maska4;
    				liczba4 = liczba4 >> 24;
    		
    				wynik = liczba1 | liczba2 | liczba3 | liczba4;
    		
    				printf ( "num=%08x\n wynik=%08x\n", num, wynik);
    	return wynik;
    };
    use function

    Code:
    float data1;
    float zma;	
    
    zma = 1;
    
    data1 = LE_2_BI(*(int *)&zma);
    fwrite(&data1, sizeof data1, 1, file_with_points);
    result 00 3F 00 47 :-(

    Why ??

    How can I write correct byte order into the file?

    Daniel

  2. #2
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    Here's some code I use to convert Big Endian ints to Little Endian ints. Perhaps you can use this to spark an idea for a new approach.

    Code:
    union  myunion {  // "myunion" is the type name. 
    	char data[8] ; 
    	int  myint ; 
    } ; 
    
    
    int fix_int(char * n, int len ) { 
    	unsigned char temp ; 
    	int i , j ; 
    	myunion mydata ; 
    
    	memcpy(mydata.data, n, len) ; // Copy data into my union 
    	
    	for (i = 0 , j = len-1 ; i < j ; ++i, --j ) {  // works for any length value 
    	
    		// To get little endian frm Big endian, swap this: 0X01020304 into this: 0X04030201 
    	
    		temp = mydata.data[i] ; 
    		mydata.data[i] = mydata.data[j] ; 
    		mydata.data[j] = temp ; 
    	} 
    		
    	return mydata.myint ;  
    }
    Mac and Windows cross platform programmer. Ruby lover.

    Quote of the Day
    12/20: Mario F.:I never was, am not, and never will be, one to shut up in the face of something I think is fundamentally wrong.

    Amen brother!

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Does your "wynik" output show you the correct value?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Oct 2007
    Posts
    12
    Yes.
    num=3f800000
    wynik=0000803f

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I've got it:
    Code:
    data1 = LE_2_BI(*(int *)&zma);
    
    fwrite(&data1, sizeof data1, 1, file_with_points);
    This assigns a float value from an integer value.
    You will need to store the int in a temporary value, then use a dereference-cast-to-float-pointer-address-of. Like you do to make the float an integer, but with float instead of int.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Another possibility:
    Code:
    void bin_rev_write(const void *value, size_t size, FILE *file)
    {
       const unsigned char *byte = value;
       for ( byte += size - 1; size--; --byte )
       {
          fwrite(byte, sizeof *byte, 1, file);
       }
    }
    
    void foo(FILE *file)
    {
       float a = 1, b = 2;
       bin_rev_write(&a, sizeof a, file);
       bin_rev_write(&b, sizeof b, file);
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Dave,

    That would indeed work. However, calling fread/fwrite many times to load and store a single float is not good for performance, compared to a few shuffle operations needed to swap byte order. [Of course, taking addresses and casting the resulting pointer is slightly outside the spec, but very few environments will have a problem with it].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Oct 2007
    Posts
    12
    Thanks for help.
    However I don't understand how to use Your tip.
    Piece of code would help how to convert int to float and use "dereference-cast-to-float-pointer-address-of".

    Why I need to store temporary value ??

    >>You will need to store the int in a temporary value, then use a dereference-cast-to-float-pointer-address-of. Like you do to make the float an integer, but with float instead of int.

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >Why I need to store temporary value ??
    You don't really. Just be sure to declare data1 as an int (or better an unsigned int):
    Code:
    int data1;
    float zma;	
    
    zma = 1;
    
    data1 = LE_2_BI(*(int *)&zma);
    fwrite(&data1, sizeof data1, 1, file_with_points);

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you don't NEED the value as a float at all, then no, you don't need to store a temporary value. If you NEED the converted value to be a float, then you need to have an integer value at some point, then convert that by a method that makes sure that the compiler doesn't realize that the value is actually an integer, which means you have to store it in a location you can take the address of.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with binary file c++
    By lucky_mutani in forum C++ Programming
    Replies: 4
    Last Post: 06-05-2009, 10:24 AM
  2. Replies: 8
    Last Post: 03-26-2007, 06:48 PM
  3. Problems in reading binary file
    By serena in forum C Programming
    Replies: 3
    Last Post: 04-14-2005, 04:54 AM
  4. Binary File
    By Bob Dylan Lover in forum C Programming
    Replies: 4
    Last Post: 07-30-2002, 01:15 PM
  5. Replies: 10
    Last Post: 06-12-2002, 04:15 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21