java - 帮助 objective c - java byte shift

标签 java c byte shift byte-shifting

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

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

从 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);
}

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

`

最佳答案

正如@Vovanium 所指出的,您将获得 double 的 long long 值,对于您的示例,它将返回 -13456。没有分数,没有指数。

在您的 shift 和 mask 操作中,您过早地转换为 int。您需要在移位和 mask 后应用石膏。此外,将其包装在一个循环中可以减少要更改的代码量。

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 不产生该位顺序,您将得到不正确的值。在这种情况下,可能需要在发送前重新排列位。

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

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

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

这只是颠倒了 long long 被解码的顺序。

关于java - 帮助 objective c - java byte shift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4087644/

相关文章:

java - 我怎样才能添加这个属性?

java - Findbugs "Method ignores exceptional return value"java.io.File.mkdirs()

java - 当您创建某种类型的对象但声明为另一种类型时,在 JAVA 中这意味着什么?

c - 声明后在 C 中使用初始化列表

c - 如何修改此程序以计算非空格字符的数量?

Java 将 00010 打印为 8

java - Cassandra数据类型点燃数据类型

c - C中递归查找中间的数字

c - 如何在字节变量中设置位(Arduino)

android - 同时读/写 Android 加密附加字节和重复