2010-11-03 75 views
0

我正在Java和iPhone/objC客戶端之間發送數據。 Java客戶端有一個已建立的中間件組件,我正在使用它來測試新客戶端與中間件的集成。目標c幫助 - 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); 
} 

當我發[WVDouble頁頭] initWithDouble:-13456.134]從objC

的Java得到雙重5.53E -322

問題出在objC方面,因爲java正在與其他開發人員一起生產nt環境。所有生產客戶端-13456.134都是轉換後的結果。

這裏是sendDouble代碼在Java客戶端使用:`

// 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

正如@Vovanium所指出的那樣,您獲得了雙倍的long long值,在您的示例中,它將返回-13456。沒有分數,沒有指數。

在你的shift和mask操作中,你太早投射到一個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的IEEE 754位模式。0:

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; 

這只是逆轉,其中很長很長解碼的順序。

+0

感謝 - 這是有道理的,但似乎我可能不明白putDouble功能我試圖轉換。下面是Java客戶端用於發送的代碼的雙重: – 2010-11-04 13:43:15

+0

/* \t *寫雙(64位)數到流。 \t */ \t私人無效putDouble(雙號)拋出IOException異常 \t { \t \t長N = Double.doubleToLongBits(數); \t \t //必須寫這些以相反的順序被comptible \t \t stream.write((int)的(N)&0x0ff); ((int)((n >>> 8))&0x0ff); \t \t stream.write((int)的((N >>> 16))&0x0ff); stream.write((int)((n >>> 24))&0x0ff); stream.write((int)((n >>> 32))&0x0ff); ((int)((n >>> 40))&0x0ff); stream.write((int)((n >>> 48))&0x0ff); \t \t stream.write((int)的((N >>> 56))&0x0ff); \t} – 2010-11-04 13:43:45

2

ObjC代碼發送長長整型的位模式(其得到通過unsignedLongLongValue),該Java代碼試圖解釋爲雙位模式。當你使用doubleValue作爲ULL訪問它時,你會得到double的位模式。

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

如果用sizeof(n)(8字節)或sizeof(i)(4字節)發送數據,您應該一次讀取8個或4個字節而不是一個字節。我懷疑,而不是你打算在同一時間發送一個字節所以也許數據類型應該是一個字節的長度應爲1

+0

感謝您認爲我的下一個問題。它現在正在java中工作,但不回到objC。但是我有足夠的信息是危險的。所以理解會來自工作,而不是閱讀。 – 2010-11-06 11:26:26