有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

关于objective c java字节移位的帮助

我正在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) 个答案

  1. # 1 楼答案

    正如@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不能生成该位顺序,则会得到错误的值。在这种情况下,可能需要在发送之前重新排列位

    Bit 63 (the bit that is selected by the mask 0x8000000000000000L) represents the sign of the floating-point number. Bits 62-52 (the bits that are selected by the mask 0x7ff0000000000000L) represent the exponent. Bits 51-0 (the bits that are selected by the mask 0x000fffffffffffffL) represent the significand (sometimes called the mantissa) of the floating-point number.

    更新:

    确保您选择了@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
    

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

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

    这正好颠倒了long的解码顺序

  2. # 2 楼答案

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

  3. # 3 楼答案

    ObjC代码传输long-long整数的位模式(由unsignedLongValue获得),Java代码试图将其解释为double的位模式。当作为ULL访问doubleValue时,应该使用doubleValue获得double的位模式

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