简体   繁体   中英

How to turn 4 bytes into a float in objective-c from NSData

Here is an example of turning 4 bytes into a 32bit integer in objective-c. The function readInt grabs 4 bytes from the read function and then converts it into a single 32 bit int. Does anyone know how I would convert 4 bytes to a float? I believe it is big endian. Basically I need a readFloat function. I can never grasp these bitwise operations.

EDIT: I forgot to mention that the original data comes from Java's DataOutputStream class. The writeFloat function accordign to java doc is

Converts the float argument to an int using the floatToIntBits method in class Float, and then writes that int value to the underlying output stream as a 4-byte quantity, high byte first.

This is Objective c trying to extract the data written by java.

- (int32_t)read{
    int8_t v;
    [data getBytes:&v range:NSMakeRange(length,1)];
    length++;
    return ((int32_t)v & 0x0ff);
}

- (int32_t)readInt {
    int32_t ch1 = [self read];
    int32_t ch2 = [self read];
    int32_t ch3 = [self read];
    int32_t ch4 = [self read];
    if ((ch1 | ch2 | ch3 | ch4) < 0){
        @throw [NSException exceptionWithName:@"Exception" reason:@"EOFException" userInfo:nil];
    }
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

OSByteOrder.h contains functions for reading, writing, and converting integer data.

You can use OSSwapBigToHostInt32() to convert a big-endian integer to the native representation, then copy the bits into a float:

    NSData* data = [NSData dataWithContentsOfFile:@"/tmp/java/test.dat"];

    int32_t bytes;
    [data getBytes:&bytes length:sizeof(bytes)];

    bytes = OSSwapBigToHostInt32(bytes);

    float number;
    memcpy(&number, &bytes, sizeof(bytes));

    NSLog(@"Float %f", number);

[data getBytes:&myFloat range:NSMakeRange(locationWhereFloatStarts, sizeof(float)]应该可以解决问题。

Given that the data comes from DataOutputStream 's writeFloat() method, then that is documented to use Float.floatToIntBits() to create the integer representation. intBitsToFloat() further documents how to interpret that representation.

I'm not sure if it's the same thing, but the xdr API seems like it might handle that representation. The credits on the man page refer to Sun Microsystems standards/specifications, so it seems likely it's related to Java.

So, it may work to do something like:

// At top of file:
#include <rpc/types.h>
#include <rpc/xdr.h>

// In some function or method:
XDR xdr;
xdrmem_create(&xdr, (char*)data.bytes + offset, data.length - offset, XDR_DECODE);
float f;
if (!xdr_float(&xdr, &f))
    /* handle error */;
xdr_destroy(&xdr);

If the data consists of a whole stream in eXternal Data Representation, then you would create one XDR stream for the whole task of extracting items from it, and use many xdr_...() calls between creating and destroying it to extract all of the items.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM