关于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);
}
//--------------------------------------------------------------------------------
`
# 1 楼答案
正如@Vovanium所指出的,您将得到double的long-long值,对于您的示例,它将返回-13456。没有分数,就没有指数
在轮班和蒙版操作中,过早地将其转换为int。您需要在移位和遮罩后应用投射。此外,将其包装在循环中可以减少要更改的代码量
请注意,根据JavaDocs for Double,Java希望位具有特定的顺序。如果从double转换为unsigned long不能生成该位顺序,则会得到错误的值。在这种情况下,可能需要在发送之前重新排列位
更新:
确保您选择了@Vovanium的更改,以便使用正确的位集:
尝试使用-1.0的值进行测试。用于-1.0的IEEE 754位模式为:
并且,当序列化时,字节将是
如果您得到以下字节:
您遇到了endian顺序问题。如果是这样的话,那么你 将示例代码中的行更改为
这正好颠倒了long的解码顺序
# 2 楼答案
如果发送的数据大小为sizeof(n)(8字节)或sizeof(i)(4字节),则一次只能读取8或4个字节,而不是一个字节。我怀疑您打算一次发送一个字节,所以数据类型可能应该是一个字节,长度应该是1
# 3 楼答案
ObjC代码传输long-long整数的位模式(由unsignedLongValue获得),Java代码试图将其解释为double的位模式。当作为ULL访问doubleValue时,应该使用doubleValue获得double的位模式