Bytevergleich in Java

Gast #7245635
Lesenswert?

Als alter C-Hase bin ich gerade dabei, ein Programm in Java zu 
schreiben, das über Bluetooth gesendete Daten empfängt. Der Datenblock 
steht in einem Byte-Array mit 10 Elementen. Die letzten beiden Elemente 
enthalten High- bze. Low byte des CRC. Den CRC berechne ich mit der 
statischen Methode crc16 einer Klasse namens CRC, die selbstverständlich 
die letzten beiden Bytes auslässt. Das funktioniert und der so 
berechnete CRC stimmt mit dem übertragenen überein. Trotzdem wirft er 
mich häufig - aller
dings nicht immer - mit einer CRCException raus:
1
 short crc = CRC.crc16(response);
2
    if ((response[8] != (crc >>> 8)) || (response[9] != (crc & 0xFF))) {
3
            throw new CRCException("CRC error");
4
    }

Der Fehler scheint immer dann aufzutreten, wenn eines der Bytes > 127 
ist. Anscheinend hat das irgendetwas mit dem Vorzeichen zu tun, 
vermutlich wandelt Java den Datentyp vor dem Vergleich vorzeichenrichtig 
in einen anderen um. Andererseits sollt ">>>" im Gegensatz zu ">>" ja 
gerade logisch und nicht arithmetisch schieben. Wie löst man das 
Problem?
PS: In C wäre das mit "unsigned short" bzw. "uint16_t" sauber und 
elegant gelöst. Leider gibt es in Java keine unsigned Datentypen.
Gast #7245788
Lesenswert?

Eine Vermutung schrieb:
> response[8] und response[9] werden vor dem != in negative shorts
> umgewandelt.
>
> Vielleicht (crc >>> 8) und (crc & 0xFF) vor dem Vergleich in byte
> casten.
In Byte casten habe ich probiert, funktioniert nicht. Offenbar werden 
Vergleiche in Java immer als Integer ausgeführt.   Man muss response[8] 
und response[9] mit 0xFF verunden, um sie wieder auf 8 bit zu 
reduzieren.
Es soll aber auch ein compareUnsigned() als Methode der Integer-Klasse 
geben, habe ich baer noch nicht getestet,
Das ist dennoch ein ziemlicher Kranpf und leider auch sehr 
fehlerträchtig.
Gast #7245866
Lesenswert?

Soweit ich weiß, werden Bytes in Java nativ als Integer behandelt. Wenn 
die Bitschubserei nicht nötig ist, kannst du sie dir sparen.

Ansonsten sind Integers und auch Bytes in Java grundsätzlich 
vorzeichenbehaftet.

Mike schrieb:
> alter C-Hase bin ich

Auch wenn die Syntax zu C ähnlich ist: Es ist nicht C. ;)
Gast #7245871
Lesenswert?

PS: Arrays benutzt in Java eigentlich niemand. In den Collections findet 
sich eigentlich immer etwas, das besser ist.

Und in deinem speziellen Fall könntest du dir mal ByteBuffer 
anschauen...ich glaube, das könnte was für dich sein.
Gast #7245957
Lesenswert?

Mike schrieb:
> Der Fehler scheint immer dann aufzutreten, wenn eines der Bytes > 127
> ist.

Also die Byte-Variablen können diese Werte (>127) gar nicht aufnehmen. 
Man kann aber die Bitstruktur mit dem Cast-Operator trotzdem übernemhem:
1
byte b1 = 0xFF; //Fehler
2
byte b2 = (byte)0xFF; // geht, b2 = -1

 "crc >>> 8" wäre aber ein Integer. Und da wäre z.B. 0xFF == 255 (als 
Integerwert). Und -1 und 255 sind logischerweise nicht gleich.

Andererseits kann eine short-Variable auch keine Wert a la 0xFF00 
aufnehmen. Man müsste wieder casten:
1
short val = (short)0xFF00;

Die Frage ist halt, welche Werte werden in dem Byte-Array (z.B. auch 
0xFF?) und in der short-Variable abgelegt.

Ich würde sagen - casten und testen.
1
 short crc = (short)CRC.crc16(response);
2

3
 if ((response[8] != (byte)(crc >>> 8)) || (response[9] != (byte)crc)) {
4
      throw new CRCException("CRC error");
5
 }
#7247565
Lesenswert?

Wühlhase schrieb:
> Das brauchst du im Allgemeinen in Java nicht zu haben. Da ist praktisch
> alles wohldefiniert, daß Compiler a etwas anderes tut als Compiler b
> kommt eigentlich nicht vor.

Du hast das Problem genau dann wenn du binäre Daten aus einer externen 
Quelle liest und die auswerten willst.
Das kann eine Datei oder Daten über einen Socket sein.
Oder Blobs aus Datenbanken, oder oder oder ...

Und das ist jetzt nicht so exotisch.
Gast #7247616
Lesenswert?

Udo S. schrieb:
> Wühlhase schrieb:
>> Das brauchst du im Allgemeinen in Java nicht zu haben. Da ist praktisch
>> alles wohldefiniert, daß Compiler a etwas anderes tut als Compiler b
>> kommt eigentlich nicht vor.
>
> Du hast das Problem genau dann wenn du binäre Daten aus einer externen
> Quelle liest und die auswerten willst.
> Das kann eine Datei oder Daten über einen Socket sein.
> Oder Blobs aus Datenbanken, oder oder oder ...
>
> Und das ist jetzt nicht so exotisch.

Wenn du aus deiner eigenen Frickelschaltungen Daten per UART 
reinschaufelst, dann kann das schon sein.
Aber ansonsten ist das Problem zumindest heute relativ selten, um diesen 
Mist haben sich schon seit längerer Zeit andere gekümmert. Ich meine, 
aus Berkely gibt es schon seit längerem eine Bibliothek dazu und 
Datenbanken, die diesen Standard nicht implementiert haben sollte man 
einfach nicht benutzen und in Ruhe sterben lassen.
Gast #7247619
Lesenswert?

PS: Java standardisiert natürlich nicht das Datenformat von z.B. 
SQL-Datenbanken.

Aber innerhalb der Javawelt ist das alles einheitlich geregelt, egal was 
die Hardware darunter vorgibt. Neben anderen Dingen ist genau das die 
Daseinsberechtigung der JVM.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren