Question

J'envoie des données entre Java et les clients iPhone / objc. Le client Java est un composant middleware établi que j'utilise pour l'intégration de test du nouveau client au middleware.

J'ai un problème avec toutes les opérations de décalage d'octets. Le code Java est en production et ne peut pas être modifiée. Depuis la double semble être le plus étendu je l'afficher.

Pour envoyer de 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 reçoit:

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

Quand j'envoie [[WVDouble alloc] initWithDouble: -13456,134] de objc

java obtient deux 5.53E-322

Le problème est du côté objc, puisque le java est en production avec d'autres environnements de développement. Avec tous les clients de production -13456,134 est le résultat converti.

Voici le code sendDouble les utilisations client 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);
}

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

`

Était-ce utile?

La solution

Comme @Vovanium a souligné, vous obtenez la valeur longue longue du double, qui pour votre exemple retourne -13456. Aucune fraction, aucun exposant.

Dans votre quart de travail et les opérations de masque que vous êtes de coulée à un int trop tôt. Vous devez appliquer le casting après le changement et le masque. En outre, l'enveloppant dans une boucle réduit la monture de code à modification.

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

Notez que la, selon le JavaDocs Double, Java attend les bits auront un ordre particulier. Vous obtiendrez des valeurs incorrectes si la coulée de la double unsigned long long ne produit pas cet ordre de bits. Dans ce cas, il peut être nécessaire de réorganiser les bits avant de l'envoyer.

Bit 63 (le bit qui est sélectionnée par le masque 0x8000000000000000L) représente le signe du nombre à virgule flottante. Bits 62-52 (les bits qui sont sélectionnés par le masque 0x7ff0000000000000L) représentent l'exposant. Les bits 51-0 (les bits qui sont sélectionnés par le masque 0x000fffffffffffffL) représenter la mantisse (parfois appelé la mantisse) du nombre à virgule flottante.

Mise à jour:

Assurez-vous que vous chercher @ changement de Vovanium si vous travaillez sur le bon ensemble de bits:

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

Essayez de tester une valeur de -1,0. La configuration de bits IEEE 754 pour une -1,0 est:

0xbff0000000000000

Et, quand sérialisé, les octets seraient

00 00 00 00 00 00 f0 bf

Si au contraire vous obtenez ces octets:

bf f0 00 00 00 00 00 00

vous rencontrez un problème d'ordre endian. Si tel est le cas, alors vous changerait la ligne dans mon code exemple

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

qui renverse tout l'ordre dans lequel le long long est décodé.

Autres conseils

codes ObjC transmet le bit de motif long long nombre entier (qui a obtenu par unsignedLongLongValue), dont le code Java tente d'interpréter comme motif de bits de double. Vous obtenez shold configuration binaire double en utilisant doubleValue, lorsque l'accès comme ULL.

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

Si vous envoyez des données avec sizeof (n) (8 octets) ou sizeof (i) (4 octets) vous devriez vous attendre à lire 8 ou 4 octets non une à la fois. Je pense plutôt que vous avez l'intention d'envoyer un octet à la fois alors peut-être le type de données doit être un octet et la longueur doit être 1.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top