سؤال

أقوم بإرسال بيانات بين عملاء 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];

}

يتلقى جافا:

/*
 * 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 inloc] initWithDouble: -13456.134] من OBJC

جافا تحصل على ضعف 5.53e-322

تكمن المشكلة في جانب OBJC ، لأن Java قيد الإنتاج مع بيئات تطوير أخرى. مع جميع عملاء الإنتاج -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);
}

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

`

هل كانت مفيدة؟

المحلول

كما أشار @Vovanium ، فإنك تحصل على القيمة الطويلة الطويلة للمزدوجة ، والتي ستعود على مثالك -13456. لا جزء ، لا الأسس.

في عمليات التحول والقناع الخاصة بك ، تقوم بإلقاء نظرة على 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 للمضاعفة, ، تتوقع Java أن يكون لدى البتات ترتيب معين. ستحصل على قيم غير صحيحة إذا كان الصب من مزدوج إلى طويل غير موقّع طويلًا لا ينتج عن ترتيب البت. في هذه الحالة ، قد يكون من الضروري إعادة ترتيب البتات قبل إرسالها.

Bit 63 (البت الذي تم تحديده بواسطة القناع 0x8000000000000000) يمثل علامة رقم النقطة العائمة. تمثل البتات 62-52 (البتات التي يتم تحديدها بواسطة القناع 0x7ff000000000000l) الأسس. تمثل البتات 51-0 (البتات التي يتم اختيارها بواسطة القناع 0x000fffffffffffl) الدلول (الذي يطلق عليه أحيانًا mantissa) لرقم النقطة العائمة.

تحديث:

تأكد من التقاط تغيير @vovanium حتى تعمل على المجموعة الصحيحة من البتات:

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

حاول الاختبار بقيمة -1.0. نمط IEEE 754 بت لـ -1.0 هو:

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;

هذا يعكس فقط الترتيب الذي يتم فيه فك تشفير الطول الطويل.

نصائح أخرى

ينقل رمز OBJC نمط بت من عدد صحيح طويل طويل (والذي حصل على قيم غير موقعة) ، والذي يحاول رمز Java تفسيره على أنه نمط بت. يمكنك الحصول على نمط بتات من المزدوج باستخدام Doublevalue ، عند الوصول إليه كـ ULL.

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

إذا قمت بإرسال بيانات ذات حجم (N) (8-BYTES) أو SizeOF (I) (4-BYTES) ، فيجب أن تتوقع قراءة 8 أو 4 بايت ليس واحدًا في كل مرة. أظن بدلاً من ذلك أنك تنوي إرسال بايت واحد في وقت واحد ، لذا ربما يجب أن يكون نوع البيانات بايت ويجب أن يكون الطول 1.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top