2017-11-05 5 views
1

Ich habe ein Problem, wo ich eine INT32 an eine andere Anwendung senden muss, aber von was ich gelesen habe, messachepack.putInt und messagepack.putLong wird versuchen, dies in UINT32 zu optimieren, die Probleme verursacht die empfangende Anwendung.Wie packe ich ein INT32 in mein MessagePack mit Java?

Die empfangende Anwendung mir die Fehlermeldung

decode error, skipping message. msgp: attempted to decode type "uint" with method for "int" 

ich mit der Abhängigkeit

<dependency> 
    <groupId>org.msgpack</groupId> 
    <artifactId>msgpack-core</artifactId> 
    <version>0.8.13</version> 
</dependency> 

Jemand anderes hatte das gleiche Problem und erklärte, die Lösung für sie bin mit Maven geben war wie

folgt

"OK, so dass wir das Problem gefunden haben, scheint es, als ob metricTank die Eigenschaft time des Nachrichtenobjekts benötigt, um als IN serialisiert zu werden T32, aber die packInt (oder packLong) wird immer versuchen, es in UINT32 zu optimieren, was MetrikTank nicht mag. also mussten wir addPayload verwenden und MessagePacker.Code.INT32 und dann die eigentlichen 4 Bytes der time-Eigenschaft serialisieren. "

Aber ich bin nicht sicher, was zu tun ist, und ich bin nicht in der Lage, die OP zu kontaktieren.

Ich habe folgendes versucht, aber es funktioniert nicht

ByteBuffer buf = ByteBuffer.allocate(1 + Long.BYTES); 
buf.put(MessagePack.Code.INT32); 
buf.putLong(md.time); 
packer.addPayload(buf.array()); 

Die Bytes Array muss 5 sein in der Länge, ist erste Byte der Kopfzeile, wobei 0xd2 und die anderen 4 Bytes müssen den Wert

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      DataOutputStream dos = new DataOutputStream(baos); 
      dos.writeLong(md.time); 
      dos.close(); 
      byte[] longBytes = baos.toByteArray(); 

      ByteBuffer lBytes = ByteBuffer.allocate(4); 
      for (int i = 0; i < 4; i++) { 
        lBytes.put(longBytes[i]); 
      } 

      ByteBuffer buf = ByteBuffer.allocate(5); 
      buf.put((byte) 0xd2); 
      buf.put(lBytes.array()); 

Th sein, Es erzeugt keinen Fehler, aber der Zeitwert ist falsch, wenn er empfangen wird.

Könnte mir jemand zeigen, wie ich ein INT32 in mein MessagePack anstelle von UINT32 packen kann oder mir zeigen, wie ich die Daten richtig verpacken kann, damit sie auf der empfangenden Anwendung korrekt entpackt wird?


Die empfangende Anwendung ist in Go geschrieben und verwendet die tinylib msgp Bibliothek, die Daten

// ReadInt64Bytes tries to read an int64 
// from 'b' and return the value and the remaining bytes. 
// Possible errors: 
// - ErrShortBytes (too few bytes) 
// - TypeError (not a int) 
func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) { 
    l := len(b) 
    if l < 1 { 
     return 0, nil, ErrShortBytes 
    } 

    lead := b[0] 
    if isfixint(lead) { 
     i = int64(rfixint(lead)) 
     o = b[1:] 
     return 
    } 
    if isnfixint(lead) { 
     i = int64(rnfixint(lead)) 
     o = b[1:] 
     return 
    } 

    switch lead { 
    case mint8: 
     if l < 2 { 
      err = ErrShortBytes 
      return 
     } 
     i = int64(getMint8(b)) 
     o = b[2:] 
     return 

    case mint16: 
     if l < 3 { 
      err = ErrShortBytes 
      return 
     } 
     i = int64(getMint16(b)) 
     o = b[3:] 
     return 

    case mint32: 
     if l < 5 { 
      err = ErrShortBytes 
      return 
     } 
     i = int64(getMint32(b)) 
     o = b[5:] 
     return 

    case mint64: 
     if l < 9 { 
      err = ErrShortBytes 
      return 
     } 
     i = getMint64(b) 
     o = b[9:] 
     return 

    default: 
     err = badPrefix(IntType, lead) 
     return 
    } 
} 

Dieser überprüft die erste Byte zu dekodieren, und, wenn das erste Byte zu mint32 gleich der ist 0xd2, dann werden die nächsten vier Bytes gelesen, was der Wert der langen ist getmint32

func getMint32(b []byte) int32 { 
    return (int32(b[1]) << 24) | (int32(b[2]) << 16) | (int32(b[3]) << 8) | (int32(b[4])) 
} 

Antwort

0

In diesem speziellen Problem musste die empfangende Anwendung eine INT32 empfangen und das Array Byte muss 5 Länge sein. Das erste Byte ist der Header 0xd2 wie im OP zu sehen. Dies teilt der Dekodiermethode mit, dass es sich um ein INT32 handelt. Die nächsten vier 4 Bytes sind der Zeitwert.

Ich habe vergessen, dass eine lange 8 Bytes ist, so müssen wir nur Epoch Times verwenden, die eine ganze Zahl ist.

 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     DataOutputStream dos = new DataOutputStream(baos); 
     dos.writeInt((int)(md.time/1000)); 
     dos.close(); 
     byte[] timeBytes = baos.toByteArray(); 


     ByteBuffer buf = ByteBuffer.allocate(5); 
     buf.put((byte) 0xd2);//header 
     buf.put(timeBytes);//time value (int32 bytes not uint32) 
Verwandte Themen