帮助客观c - java字节移位

时间:2010-11-03 13:46:23

标签: java c byte shift byte-shifting

我在Java和iPhone / objC客户端之间发送数据。 Java客户端有一个已建立的中间件组件,我用它来测试新客户端与中间件的集成。

我的所有字节移位操作都有问题。 Java代码正在生产中,无法修改。由于双重似乎是最广泛的我会发布它。

从objC发送:

-(void)putDouble:(NSNumber *)v{

    unsigned long long n = [v unsignedLongLongValue];

    dataToSend = [NSMutableData data];

    long long i = (int)n & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 8) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 16) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 24) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 32) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];


    i = ((int)n >> 40) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];


    i = ((int)n >> 48) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];


    i = ((int)n >> 56) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];
    [self send:dataToSend];

}

Java收到:

/*
 * Retrieve a double (64-bit) number from the stream.
 */
private double getDouble() throws IOException
{
    byte[] buffer = getBytes(8);

    long bits =
            ((long)buffer[0] & 0x0ff) |
            (((long)buffer[1] & 0x0ff) << 8) |
            (((long)buffer[2] & 0x0ff) << 16) |
            (((long)buffer[3] & 0x0ff) << 24) |
            (((long)buffer[4] & 0x0ff) << 32) |
            (((long)buffer[5] & 0x0ff) << 40) |
            (((long)buffer[6] & 0x0ff) << 48) |
            (((long)buffer[7] & 0x0ff) << 56);

    return Double.longBitsToDouble(bits);
}

从objC发送[[WVDouble alloc] initWithDouble:-13456.134]时

java获取双倍5.53E-322

问题出在objC方面,因为java正在与其他开发环境一起生产。对于所有生产客户,-13456.134是转换结果。

这是java客户端使用的sendDouble代码:`

 // Write a double (64-bit) number to the stream.

private void putDouble(double number) throws IOException
{
    long n = Double.doubleToLongBits(number);

    // have to write these in reverse order to be comptible

    stream.write((int)(n) & 0x0ff);
    stream.write((int)((n >>> 8)) & 0x0ff);
    stream.write((int)((n >>> 16)) & 0x0ff);
    stream.write((int)((n >>> 24)) & 0x0ff);
    stream.write((int)((n >>> 32)) & 0x0ff);
    stream.write((int)((n >>> 40)) & 0x0ff);
    stream.write((int)((n >>> 48)) & 0x0ff);
    stream.write((int)((n >>> 56)) & 0x0ff);
}

//--------------------------------------------------------------------------------

`

3 个答案:

答案 0 :(得分:3)

正如@Vovanium指出的那样,你得到了double的long long值,对于你的例子,它将返回-13456。没有分数,没有指数。

在你的转换和掩码操作中,你过早地转换为int。您需要在班次和面具后应用演员表。此外,将其包装在一个循环中可以减少要更改的代码。

int i;
int j;

for (j = 0; j < sizeof(n); j++) {
    i = (int)(n >> (j*8)) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];
}
[self send:dataToSend];

请注意,根据JavaDocs for Double,Java期望这些位具有特定的顺序。如果从double转换为unsigned long long不会产生该位顺序,则会得到不正确的值。在这种情况下,可能需要在发送之前重新排列位。

位63(由掩码0x8000000000000000L选择的位)表示浮点数的符号。位62-52(由掩码0x7ff0000000000000L选择的位)表示指数。位51-0(由掩码0x000fffffffffffffL选择的位)表示浮点数的有效位数(有时称为尾数)。

<强>更新

确保你选择@ Vovanium的更改,这样你就可以使用正确的位:

double nd = [v doubleValue];
unsigned long long n = *(long long *)&nd;

尝试使用值-1.0进行测试。 -1.0的IEEE 754位模式是:

0xbff0000000000000

并且,在序列化时,字节将是

00 00 00 00 00 00 f0 bf

如果你得到这些字节:

bf f0 00 00 00 00 00 00

您遇到了序列码问题。如果是这样,那么你 会将我的示例代码中的行更改为

    i = (int)(n >> ((sizeof(n) - j - 1)*8)) & 0x0ff;

这只会颠倒解码long long的顺序。

答案 1 :(得分:2)

ObjC代码传输长整数的位模式(由unsignedLongLongValue获取),Java代码试图将其解释为double的位模式。当你将其作为ULL访问时,你可以使用doubleValue获取double模式。

double nd = [v doubleValue];
unsigned long long n = *(long long *)&nd;

答案 2 :(得分:1)

如果发送sizeof(n)(8字节)或sizeof(i)(4字节)的数据,则应该一次读取8或4个字节,而不是一个。我怀疑你打算一次发送一个字节,所以数据类型可能是一个字节,长度应该是1。