2009-04-10 16 views
21

Ich lese 133 Länge Paket von Serialport, die letzten 2 Bytes enthalten CRC-Werte, 2 Bytes Wert habe ich Single (kurz ich denke) mit Java. das, was ich getan habe,2 Bytes zu kurz Java

short high=(-48 & 0x00ff); 
short low=80; 

short c=(short) ((high<<8)+low); 

aber ich bin nicht korrekte Ergebnis bekommen, ist es Problem, weil bewertet unterzeichnet? Wie kann ich dieses Problem lösen, plz helfen Sie mir, ich bin in Schwierigkeiten

+0

Gibt es einen bestimmten Grund, warum Sie kurz anstelle von int verwenden? Ist Ihr CRC-Wert nicht vorzeichenlos? – akarnokd

Antwort

54

Denken Sie daran, Sie müssen sich nicht in Knoten mit Bit Verschiebung binden, wenn Sie nicht zu vertraut mit den Details sind. Sie können eine ByteBuffer verwenden Sie, um zu helfen:

ByteBuffer bb = ByteBuffer.allocate(2); 
bb.order(ByteOrder.LITTLE_ENDIAN); 
bb.put(firstByte); 
bb.put(secondByte); 
short shortVal = bb.getShort(0); 

Und umgekehrt, können Sie eine kurze setzen, dann Bytes herausziehen.

Übrigens fördern bitweise Operationen die Operanden automatisch auf mindestens die Breite eines int. Es gibt wirklich keine Vorstellung davon, "dass man ein Byte nicht um mehr als 7 Bits verschieben darf" und andere Gerüchte, die sich zu drehen scheinen.

+0

du hast Recht, es fördert zu int so Verschiebung um 7 ist in Ordnung. Aber << 32 ist undefiniert, also tut es nichts. – CookieOfFortune

+0

Ich finde, dass "Converting" -Puffer der Größe 8192 fast immer dauert, wenn der Debugger an das Gerät angeschlossen ist. Gibt es eine Möglichkeit, den gesamten Puffer auf einmal zu konvertieren? –

+1

RE: "Sie müssen sich nicht mit Bit-Shifting verknoten"; meiner Erfahrung nach (und es ist ziemlich beachtlich, da die meiste Zeit meiner Karriere in Comms ist), wenn man sich mit Comms-Protokollen dieser Art beschäftigt, sollte man sich besser mit Bitmanipulationen vertraut machen. –

20

Wenn Sie Bytewerte aus einem Stream in numerische Werte in Java konvertieren, müssen Sie sehr vorsichtig mit der Zeichenerweiterung sein. Es gibt eine Falle mit negativen Zahlen (Werte von (vorzeichenlos) 128-255).

Versuchen Sie dies (es funktioniert, wenn hallo und lo sind alle Integer-Typ Java):

short val=(short)(((hi&0xFF)<<8) | (lo&0xFF)); 

Ich finde es am besten mit den Klammern in diesen Fällen explizit sein.

+2

Sie brauchen die Umwandlungen nicht zu int, was implizit für die & Operationen geschieht. – starblue

7

Die anderen Antworten sind in Ordnung, aber ich möchte einen Schwerpunkt auf die Art setzen:

short high=(-48 & 0x00ff); 
short low=80; 

int c= ((high & 0xFF) << 8) | (low & 0xFF); 

Der short Typ kann Werte zwischen 32768 bis 32767 53328 kann nicht schön kurz gespeichert werden, repräsentieren Verwendung int statt, wie es Ihnen erlaubt, vorzeichenlosen Wert bis zu ~ 10 Speichern Sie also nicht den Ausdruck zu kurz, wie es Ihnen den signierten Wert net.

+0

Wenn Sie mit 16-Bit-CRCs arbeiten, brauchen Sie nur das korrekte Bitmuster. Es spielt keine Rolle, ob der letzte Java-Wert signiert ist. –

+0

Danke, ich habe '& 0x00FF' aus der ersten Zeile verwendet, um ein vorzeichenloses Byte in einen kurzen Wert zu konvertieren. Wenn Sie zum Beispiel 0x87 auf einen kurzen Wert setzen, erhalten Sie -121 anstelle von 135. – wrapperapps

2

Dies geschieht, wenn man versucht, Bytes zu verketten (sehr subtil)

byte b1 = (byte) 0xAD; 
byte b2 = (byte) 0xCA; 
short s = (short) (b1<<8 | b2); 

Die oben erzeugt 0xFFCA, was falsch ist. Dies liegt daran, dass b2 negativ ist (Byte-Typ ist signiert!), Was bedeutet, dass wenn es in den int-Typ für das bitweise | konvertiert wird Operation, wird es links gepolstert mit 0xF!

Daher müssen Sie daran denken, das gepolsterte Bytes zu maskieren-out, so dass sie auf jeden Fall gleich Null sein:

short s = (short) (b1<<8 | b2 & 0xFF); 
0

Sie 2 Bytes zu einem Kurzschluss in einer besser lesbaren und eleganten Art und Weise umwandeln können.

short s = ByteBuffer.wrap(new byte[]{0x01, 0x02}).getShort(); 
// now short equals 258 

Das erste Byte ist das höchstwertige Byte.

Verwandte Themen