Frage

Ich bin das Senden von Daten zwischen Java und iPhone / ObjC Kunden. Das Java-Client hat eine Middleware-Komponente festgestellt, dass ich an die Middleware zu Test Integration des neuen Client verwenden.

habe ich ein Problem mit alle Byte Schichtbetrieb. Der Java-Code ist in der Produktion und kann nicht geändert werden. Da die Doppel die umfangreichste zu sein scheint, ich werde es posten.

von ObjC senden:

-(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 erhält:

/*
 * 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);
}

Wenn ich sende [[WVDouble alloc] initWithDouble: -13.456,134] von ObjC

java bekommt Doppel 5.53E-322

Das Problem ist auf der ObjC Seite, da die Java in der Produktion mit anderen Entwicklungsumgebungen ist. Bei allen Produktionskunden -13456,134 ist das konvertierte Ergebnis.

Hier ist der sendDouble Code der Java-Client verwendet: `

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

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

`

War es hilfreich?

Lösung

Wie spitz @Vovanium aus, bist du den langen langen Wert des Doppels bekommen, die für Ihr Beispiel -13456 zurück. Keine Fraktion, kein Exponent.

In Ihrer Schicht und Maskenoperationen Sie sind Gießen zu einem noch zu früh, int. Sie müssen die Besetzung nach der Verschiebung und Maske anzuwenden. Außerdem ist es nach oben in einer Schleife Einwickeln reduziert sich die Montage des Codes zu ändern.

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];

Zu beachten ist, dass nach dem JavaDocs für Doppel erwartet Java die Bits eine bestimmte Reihenfolge haben. Sie werden falsche Werte erhalten, wenn von doppelt auf unsigned Gießen nicht lange, lange nicht, dass etwas Ordnung herzustellen. In diesem Fall kann es erforderlich sein, die Bits neu zu ordnen, bevor senden.

63 Bit (das Bit, das durch die Maske 0x8000000000000000L ausgewählt ist) stellt das Vorzeichen der Gleitkommazahl. Bits 62-52 (die Bits, die durch die Maske 0x7ff0000000000000L ausgewählt sind) stellen den Exponenten. Bits 51-0 (die Bits, die durch die Maske 0x000fffffffffffffL ausgewählt sind) stellen die Mantisse der Gleitkommazahl (manchmal die Mantisse bezeichnet).

Update:

Stellen Sie sicher, wählen Sie @ Vovanium die Änderung, so dass Sie auf dem richtigen Satz von Bits arbeiten:

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

Versuchen Sie, mit einem Wert von -1,0 testen. Die IEEE 754-Bit-Muster für eine -1.0 ist:

0xbff0000000000000

Und wenn serialisiert, würden die Bytes

00 00 00 00 00 00 f0 bf

Wenn Sie stattdessen diese Bytes erhalten:

bf f0 00 00 00 00 00 00

Sie stoßen ein Endian Problem. Wenn das der Fall ist, dann sind Sie würde die Zeile in meinem Beispiel-Code ändern

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

Das kehrt nur die Reihenfolge, in der die lange langen dekodiert wird.

Andere Tipps

ObjC Code sendet Bitmuster long long integer (die durch unsignedLongLongValue bekam), die Java-Code versucht als Bitmuster Doppel zu interpretieren. Sie shold Bitmuster Doppel mit double, wenn der Zugang als ULL erhalten.

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

Wenn Sie Daten mit sizeof (n) (8-Byte) oder sizeof (i) (4-Byte) senden sollten Sie erwarten, 8 oder 4 Bytes nicht einer nach dem anderen zu lesen. Ich vermute, stattdessen Sie beabsichtigen, vielleicht sollte der Datentyp ein Byte sein, so zu einem Zeitpunkt ein Byte zu senden und die Länge sollte 1.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top