Forum: PC-Programmierung Bytevergleich in Java


von Mike (Gast)


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.

von Eine Vermutung (Gast)


Lesenswert?

response[8] und response[9] werden vor dem != in negative shorts 
umgewandelt.

Vielleicht (crc >>> 8) und (crc & 0xFF) vor dem Vergleich in byte 
casten.

von Mike (Gast)


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.

von Wühlhase (Gast)


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. ;)

von Wühlhase (Gast)


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.

von ein lupenreiner Demokrat (Gast)


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
 }

von Mike (Gast)


Lesenswert?

Wühlhase schrieb:
> Und in deinem speziellen Fall könntest du dir mal ByteBuffer
> anschauen...ich glaube, das könnte was für dich sein.

Danke, tut genau, was es soll. Die Klasse kannte ich bisher noch nicht 
und hatte zunächst Bedenken wegen der Endianess.

von Wühlhase (Gast)


Lesenswert?

Mike schrieb:
> Bedenken wegen der Endianess

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.

Einer der großen Unterschiede zu C.

von arbeitsloser Intendant (Gast)


Lesenswert?


von Udo S. (urschmitt)


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.

von arbeitsloser Intendant (Gast)


Lesenswert?

Udo S. schrieb:
> Und das ist jetzt nicht so exotisch.

Auch dafür gibts zig Hilfsmethoden/Klassen, notfals verdreht man die 
bytes selbst. Wo ist das Problem? Sind wir hier im Kindergarten?

von Wühlhase (Gast)


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.

von Wühlhase (Gast)


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.

von Udo S. (urschmitt)


Lesenswert?

Wühlhase schrieb:
> und
> Datenbanken, die diesen Standard nicht implementiert haben sollte man
> einfach nicht benutzen und in Ruhe sterben lassen.

Klar, also sagt man dem lukrativen Kunden such dir einen anderen.

Kann man machen, aber vieleicht nicht so oft ;)

: Bearbeitet durch User
von Wühlhase (Gast)


Lesenswert?

Ich sag mal so: in Cobol zu programmieren ist heute auch lukrativ. ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.