Datentypen byte als unsigned interpretieren

kodela

Bekanntes Mitglied
Hallo,

aus reinem Interesse an der Sache versuche ich ein vor vielen vielen Jahren von mir in C++ geschriebenes Schachprogramm nach Java zu übersetzen. Ich bin damit schon relativ weit gekommen, hänge jetzt aber an der Eröffnungsbibliothek.

Diese umfasst knapp 30.000 Züge und muss aus einer Datei eingelesen werden. Jedes Byte dieser Datei enthält in den ersten sechs Bits eine Zugnummer, über die der Zug festgestellt werden kann. Die beiden anderen Bits stehen für vier Attribute, über die Folgezüge und Varianten angezeigt werden.

In C++ werden die Bytes als Char-Typen eingelesen und auch behandelt. Da in Java der Typ Char 16 Bit hat, lese ich die Datei als Bytes ein. So lange für die Feststellung eines Zuges das Bit 7 keine Bedeutung hat, funktioniert alles. Das ändert sich mit dem letzten Byte einer Variante. Dieser Zustand wird durch das gesetzte Bit 7 angezeigt. Wenn aber das Bit 7 gesetzt ist, wird der gesamte Wert des Bytes als negativer Wert interpretiert, was naturgemäß zu einem falschen Ergebnis führen muss.

Ich könnte nun zwar die gesamte Datei mit der Eröffnungsbibliothek so speichern, dass jedes Byte als Short gespeichert und in Zukunft die Auswertung über diese Short-oder Char-Daten vorgenommen wird. Dies möchte ich aber nur als allerletzte Möglichkeit in Erwägung ziehen. Meine Versuche, die Byte-Daten per Casting nach Char doch als unsigned Werte zu behandeln, waren leider nicht erfolgreich.

Hat jemand eine Idee, wie ich dieses verflixte Bit 7 abfragen kann, ohne dass sich auch der übrige Wert ändert?

Hier der Code, mit dem ich die Eröffnungsbibliothek einlese:
Java:
// Einlesen der EB nach openings
try {
    File f = new File(libPath + File.separator + iniDat);
    long lenLib = f.length();
    if (lenLib == 0) {
        JOptionPane.showMessageDialog(null,
        "[InfoText]");
        return false;
    }
    oplibSize = (int)lenLib;
    openings = new byte[oplibSize];
    try (InputStream in = new FileInputStream(f)) {
        in.read(openings);
    }
} catch (IOException e) {
    JOptionPane.showMessageDialog(null,
    "[InfoText]");
    return false;
}

Und hier noch ein Beispiel für die Auswertung:
Java:
while ((((int)openings[libNo] & 0x3F) != opCount) &&    // solange Zug nicht gefunden
        ((int)openings[libNo] < 0x80)) {                // und Variante vorhanden
    nextLibNo(false);                                   // nächsten Variantenblock suchen
}

Schon im Voraus ein Danke für jede Idee, die mir hilft, meine EB auch unter Java in etwa so wie unter C++ verwenden zu können.

kodela
 

httpdigest

Top Contributor
Java:
byte signedByte = ...;
int unsigned = signedByte & 0xFF;
In `unsigned` kannst du dann das achte Bit prüfen.
 

sascha-sphw

Top Contributor
Hier würde ich aber noch erweitern, dass int generell nicht unsigned ist. Hier funktioniert das, weil int 4 bytes hat und somit das Vorzeichen Bit nicht berührt wird und der Wert somit positiv bleibt.
 

kodela

Bekanntes Mitglied
Das Problem ist, dass einerseits Bit 7 richtig abgefragt wird, was mit dem Vorschlag von httpdigest für ein Byte erreicht werden könnte, aber rechts von Bit 7 steht ja auch noch etwas, was durch die negative Interpretation des Gesamtwertes auf Grund des führend gesetzten Bits 7 sich ja auch verändert.
 

httpdigest

Top Contributor
Wenn du ein Byte mit dem Bitpattern 11010011 hast und du &0xFF darauf anwendest, hast du ein int mit dem Bitpattern `00000000 00000000 00000000 11010011`. Es findet hier kein sign-extend statt.
 

mihe7

Top Contributor
Das Problem ist, dass einerseits Bit 7 richtig abgefragt wird, was mit dem Vorschlag von httpdigest für ein Byte erreicht werden könnte, aber rechts von Bit 7 steht ja auch noch etwas, was durch die negative Interpretation des Gesamtwertes auf Grund des führend gesetzten Bits 7 sich ja auch verändert.
Ich versteh nur Bahnhof :)
 

httpdigest

Top Contributor
Ja, mein neuronales Netzwerk ist sich auch nicht sicher, welches Problem da eigentlich genau gemeint ist. Mit Confidence 49.99% ist es Problem "Ich caste nach int und dadurch bekomme ich ein sign-extend" und mit Confidence 50.01% ist es: "Ich weiss nicht genau, was das Problem ist und habe nur eine Vermutung, ob das, was ich da erzähle, eigentlich überhaupt ein Problem darstellt und frage einfach mal wirr in den Raum." :)

Deswegen probe ist jetzt mal die 49.99%-Confidence-Vermutung:

@kodela Du darfst das byte nicht explizit auf int casten bevor du die bitweise UND-Verknüpfung anwendest. Das Casten auf int führt dann zu einem sign-extend, so dass das 8. Bit IMMER 0 ist. Also einfach direkt auf dem byte & 0xFF anwenden.
 

kodela

Bekanntes Mitglied
Nein, das hat mit Schröder Katze nichts zu tun, es hat allein mit einer falschen Beurteilung meinerseits etwas zu tun. Tut mir Leid. Der Mensch irrt, so lange er strebt. Java interpretiert den gesamten Wert negativ wenn in einem Byte das Bit 7 gesetzt ist. Wird der Rest ohne diesem gesetzten Bit 7 abgefragt, dann ist das Ergebnis positiv und auch richtig. Entschuldigt bitte meinen Denkfehler und vielen Dank für all die Hinweise.

kodela
 

mihe7

Top Contributor
@kodela, kein Grund, sich für irgendwas zu entschuldigen. Ich habe in #44 nur nicht verstanden, was der Satz bedeuten soll (und verstehe ihn bis jetzt nicht :))
 

kodela

Bekanntes Mitglied
Hallo,

ja, ich denke, die Lösung liegt in einer Änderung der Abfrage. Unter C hatte ich für das EB-Array den Typ Char. Dieser Typ hat eine Länge von 8 Bit, also einem Byte. In Java hat Char eine Länge von zwei Byte, weshalb ich es mit dem Typ Byte versuchte. Unter C ergibt die Abfrage auf gesetztes Bit 7 mit if ((Char-Wert & 0x80) > 0) true, wenn es gesetzt ist. Unter Java muss ich statt dessen die Abfrage so formulieren: ((Byte-Werte & 0x80) == 0x80), denn das führende Bit gibt für das signed Byte ja einen negativen Wert.

Um allerdings sicher zu sein, muss ich noch einiges überprüfen, denn dieser Byte-Wert muss eventuell für eine Bearbeitung der EB auch editiert werden. Bevor ich das alles auf Herz und Nieren überprüfen kann, muss ich mich mit einer anderen Baustelle beschäftigten, auf der auch nicht alles rund läuft.

kodela
 

mrBrown

Super-Moderator
Mitarbeiter
Unter C ergibt die Abfrage auf gesetztes Bit 7 mit if ((Char-Wert & 0x80) > 0) true, wenn es gesetzt ist. Unter Java muss ich statt dessen die Abfrage so formulieren: ((byte-Werte & 0x80) == 0x80), denn das führende Bit gibt für das signed Byte ja einen negativen Wert.
Ich finde die Java-Variante sinnvoller und würde es auch in C so schreiben, bzw das ganze sogar direkt binär schreiben:
(b & 0b10000000) == 0b10000000
 

mihe7

Top Contributor
Unter Java muss ich statt dessen die Abfrage so formulieren: ((Byte-Werte & 0x80) == 0x80), denn das führende Bit gibt für das signed Byte ja einen negativen Wert.
Code:
jshell> byte b = (byte) 0xff
b ==> -1

jshell> (b & 0x80) > 0
$2 ==> true

jshell> if ((b & 0x80) > 0) System.out.println("true");
true
 

temi

Top Contributor
Ich finde die Java-Variante sinnvoller und würde es auch in C so schreiben, bzw das ganze sogar direkt binär schreiben:
(b & 0b10000000) == 0b10000000
Und ich würde noch Konstanten für die Variantenabfrage einführen private final static byte VARIANTE_A = (byte)0b10000000; und (b & VARIANTE_A) == VARIANTE_A
 
Zuletzt bearbeitet:

kodela

Bekanntes Mitglied
Wau, danke für Euer Interesse!

Und, ich würde es heute in C auch anders schreiben, aber als ich vor 25 Jahren an diesem Programm arbeitete, war vieles anders, angefangen mit meinem Wissen zum Programmieren mit der für mich ersten leistungsfähigen Hochsprache, das ich mir mit diesem Programm über knapp 10 Jahre hinweg erarbeitete.

Zum Vorschlag mit den Konstanten, klar, solche verwende ich reichlich, würden hier aber nicht unbedingt mehr Klarheit bringen, da dann ja auch gezeigt werden müsste, für was zum Beispiel "VARIANTE_A " steht.

Nur noch einmal zur Erinnerung. Wie ich in meinem ersten Beitrag geschrieben habe, geht es mir nur darum, was man alles anstellen muss, um ein relativ komplexes C++ Programm mit möglichst wenig Änderungen nach Java zu übersetzen. Diese Aufgabe hat mich besonders gereizt, weil ich mich selbst wundere, wie leistungsfähig auch heute noch ein Programm aus den 90er Jahren sein kann. Wer sich dafür interessiert, kann sich bowili-Schach, so habe ich es genannt, weil die Basis dieses Programms ein Demo-Projekt zu Borlands Object Windows Library war, ja einmal ansehen. Manches funktioniert zwar nicht mehr, zum Beispiel die Hilfe-Datei, anderes ist längst überflüssig, zum Beispiel die Kalibrierung der Zeitmessung nach dem ersten Start, aber im Grunde ist das Programm heute etwa um den Faktor 100 leistungsfähiger als früher. Zur Entwicklungszeit wurden in einer Sekunde etwa 30.000 Züge überprüft. Heute sind es durchschniittlich 3 Millionen.

kodela
 

mrBrown

Super-Moderator
Mitarbeiter
Zum Vorschlag mit den Konstanten, klar, solche verwende ich reichlich, würden hier aber nicht unbedingt mehr Klarheit bringen, da dann ja auch gezeigt werden müsste, für was zum Beispiel "VARIANTE_A " steht.
Wenn das Ding passend benannt ist, wird doch genau damit gezeigt, was gemeint ist :) VARIANTE_A ist ja hier nur ein Platzhalter für einen sinnvollen Namen.
 

mihe7

Top Contributor
Borlands Object Windows Library war,
LOL, das Teil hatte ich auch, ich meine Version 3.x; in einer Box mit gefühlt 25 fetten Handbüchern :)

BTW: wo man aufpassen muss in Java ist, wenn man mit dem Right Shift Operator arbeitet. Hier hat Java extra einen unsigned operator ">>>", den man tunlichst verwenden sollte, will man keine bösen Überraschungen bzgl. des Vorzeichens erleben.
 

kodela

Bekanntes Mitglied
Wenn das Ding passend benannt ist, wird doch genau damit gezeigt, was gemeint ist :) VARIANTE_A ist ja hier nur ein Platzhalter für einen sinnvollen Namen.
Ja, mir ist schon klar, was gemeint war, aber im konkreten Fall geht es doch um einen ganz bestimmten Wert für eine Verknüpfung, über die abgefragt werden soll, ob es zum aktuellen Zug, der über die ersten sechs Bits bestimmt ist, eine Fortsetzung oder eine Variante gibt. Wenn das nicht der Fall ist, dürfte von den letzten beiden Bits nur das Bit sieben gesetzt sein. Um dies im konkreten Fall zu ermitteln, sie die Abfrage so aus:
if (((openings[libNo] & 0xFF) & 0x80) == 0x80)

Man könnte natürlich für FF-Maske schlicht und einfach die Konstante ALLE und für das Bit sieben zum Beispiel END definieren. Das sähe dann so aus:
if (((openings[libNo] & ALLE) & END) == END)

Wenn ich das in meinem Programm so mache, ist das wohl ok. Wenn ich aber hier nach einer Lösung suche, wie ich für einen signierten Byte-Wert die Abfrage gestalte, dann scheint mir die erste Variante ausnahmsweise doch informativer zu sein.

das Teil hatte ich auch, ich meine Version 3.x; in einer Box mit gefühlt 25 fetten Handbüchern
Nein, 25 meist dicke Handbücher (in deutscher Sprache) waren es nicht, aber alle nebeneinander gestllt benötigten sie schon einen Meter Platz.

kodela
 

mrBrown

Super-Moderator
Mitarbeiter
Ja, mir ist schon klar, was gemeint war, aber im konkreten Fall geht es doch um einen ganz bestimmten Wert für eine Verknüpfung, über die abgefragt werden soll, ob es zum aktuellen Zug, der über die ersten sechs Bits bestimmt ist, eine Fortsetzung oder eine Variante gibt. Wenn das nicht der Fall ist, dürfte von den letzten beiden Bits nur das Bit sieben gesetzt sein. Um dies im konkreten Fall zu ermitteln, sie die Abfrage so aus:
if (((openings[libNo] & 0xFF) & 0x80) == 0x80)

Man könnte natürlich für FF-Maske schlicht und einfach die Konstante ALLE und für das Bit sieben zum Beispiel END definieren. Das sähe dann so aus:
if (((openings[libNo] & ALLE) & END) == END)

Wenn ich das in meinem Programm so mache, ist das wohl ok. Wenn ich aber hier nach einer Lösung suche, wie ich für einen signierten Byte-Wert die Abfrage gestalte, dann scheint mir die erste Variante ausnahmsweise doch informativer zu sein.
Die Abfrage kannst du kürzen zu if ((openings[libNo] & 0x80) == 0x80), das Und ist assoziativ :)

Ehrlich gesagt seh ich das Anfangsproblem aber auch gar nicht, man kommt ja auch ohne explizites Verenden mit 0xFF an jedes Bit?

(yx & MASK) != 0 oder (yx & MASK) == MASK sind zumindest mMn dabei die einfachste Varianten, man muss halt nur einen explizites gleich oder ungleich nutzen, und kein größer/kleiner, würde ich in C nicht anders machen.
 

kodela

Bekanntes Mitglied
Die Abfrage kannst du kürzen zu if ((openings[libNo] & 0x80) == 0x80), das Und ist assoziativ :)

Ehrlich gesagt seh ich das Anfangsproblem aber auch gar nicht, man kommt ja auch ohne explizites Verenden mit 0xFF an jedes Bit?

(yx & MASK) != 0 oder (yx & MASK) == MASK sind zumindest mMn dabei die einfachste Varianten, man muss halt nur einen explizites gleich oder ungleich nutzen, und kein größer/kleiner, würde ich in C nicht anders machen.

Ja, das ist alles richtig und ich weiß heute mehr darüber, wie man Byte-Werte bitweise abfragen kann, genauer, wie man abfragen muss, um keine falschen Ergebnisse zu bekommen, wenn es um das Bit 7 geht. Das verdanke ich allen, die sich meinem Thema angenommen haben. Ich muss zugeben, dass es eine ganze Weile gedauert hat bis mir bewusst wurde, dass das Problem an meiner Verwendung von Vergleichsoperatoren liegt und nicht an der Behandlung von signed-Byte-Werten durch Java.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Thallius unsigned byte Allgemeine Java-Themen 18
T "unsigned" byte[] -> BigInteger Allgemeine Java-Themen 2
LucasGlockner Effizienter byte-Zugriff auf ein long[]-Array Allgemeine Java-Themen 8
Encera Größe eines Objektes in Byte berechnen Allgemeine Java-Themen 2
M Optimierung einer Methode (byte-Geraffel) Allgemeine Java-Themen 2
Noahscript Aus einem byte Array Steuerungszeichen und Code bekommen und ersetzen Allgemeine Java-Themen 3
N Byte Array in Java "dekomprimieren" Allgemeine Java-Themen 3
W String -> byte[] -> String - Sieht jemand was ich nicht sehe? Allgemeine Java-Themen 10
TheWhiteShadow 2D-Grafik GIF Library mit byte output Allgemeine Java-Themen 10
K Data Konverter - Probleme mit Byte[] Kodierung Allgemeine Java-Themen 3
kodela Byte Order Mark (BOM) bei readLine() ignorieren Allgemeine Java-Themen 5
A Byte zu String Allgemeine Java-Themen 4
RalleYTN Datentypen Unsignierter Byte zum signierten Byte Allgemeine Java-Themen 2
X Datentypen Byte geht nicht höher als 126 auch nicht mit casten? Allgemeine Java-Themen 22
R Byte Array Zeichensuche Allgemeine Java-Themen 6
M Null byte in verschiedenen charsets Allgemeine Java-Themen 2
S Byte Array welches in Laufzeit aufgelöst wird // Objekt Array Allgemeine Java-Themen 3
O Byte-Array zu String Allgemeine Java-Themen 7
D Decodierung von Mp3-byte[] Allgemeine Java-Themen 4
A ByteBuffer.get(byte[] dst,int offset,int length) Allgemeine Java-Themen 2
A RandomAccessFile.read(byte[] b) Allgemeine Java-Themen 9
P Datentypen Warum überhaupt Byte ? Allgemeine Java-Themen 12
P Datentypen String-Daten zu Byte-Zahlen konvertieren - Komme nicht weiter nach vielem versuchen :-/ Allgemeine Java-Themen 7
E Byte zu String & umgekehrt Allgemeine Java-Themen 3
B BufferedWriter in InputStream oder Zeichen-Stream in Byte-Stream Allgemeine Java-Themen 5
M Chart per byte[] in JSP anzeigen Allgemeine Java-Themen 4
E int in byte Allgemeine Java-Themen 6
R ArrayList byte[] abspeichern Allgemeine Java-Themen 4
S byte [] in string und zurück konvertieren Allgemeine Java-Themen 2
G byte ? : Allgemeine Java-Themen 7
E Byte-Array to String: Zeichenkaputt Allgemeine Java-Themen 11
R In einem Byte-Array nach einer gewissen Zahlenfolge suchen Allgemeine Java-Themen 7
hdi Speicherbelegung byte, short, int Allgemeine Java-Themen 8
J byte - hex - byte.. casten Allgemeine Java-Themen 8
R byte[] to String Konvertieren Allgemeine Java-Themen 14
A Input/Output Buffered Image zu Byte Array und zurück konvertieren Allgemeine Java-Themen 4
M byte array splitten Allgemeine Java-Themen 3
J Hex-String zu byte transformieren Allgemeine Java-Themen 7
T Zu doof für byte-Umrechnung ... Allgemeine Java-Themen 3
W CRC32 aus byte array Allgemeine Java-Themen 5
F byte[] aus einem BufferedImage Allgemeine Java-Themen 3
L byte -> byte[1] -> byte Allgemeine Java-Themen 2
P Einzelne Bits in einem Byte-Array setzen Allgemeine Java-Themen 2
Kr0e Synchronisieren: boolean,byte,char ? Allgemeine Java-Themen 2
S Überprüfung/Parsen eines Byte-Arrays Allgemeine Java-Themen 9
Semox Byte-Manipulation eines Bildes Allgemeine Java-Themen 7
Meldanor For-Schleifen - byte statt int? Allgemeine Java-Themen 11
C int zu byte cast - verständnis Allgemeine Java-Themen 3
R int to byte[] Array Allgemeine Java-Themen 4
MQue byte[] Array to Integer Allgemeine Java-Themen 4
MQue Byte to Int convertieren Allgemeine Java-Themen 2
R Double Werte aus byte[] auslesen Allgemeine Java-Themen 5
W Verwendung von byte Allgemeine Java-Themen 9
G zu lange Byte code dateien Allgemeine Java-Themen 6
G String in byte- Array Allgemeine Java-Themen 3
E Byte [] nach hex, dann nach dec Allgemeine Java-Themen 2
A Performance: byte[] in byte[][][] konvertieren Allgemeine Java-Themen 2
G 2 x byte zusammenkopieren Allgemeine Java-Themen 7
G byte nach int Allgemeine Java-Themen 3
foobar Object to byte[] ohne Serializable Allgemeine Java-Themen 6
data89 Die Größe eines Strings in Byte berechnen? Allgemeine Java-Themen 12
G Byte- List mit einem Iterator durchlaufen Allgemeine Java-Themen 5
W Konflikt byte->int, in.read->arraycopy Allgemeine Java-Themen 7
F byte in hex-String oder: Wer hat in Mathe aufgepasst Allgemeine Java-Themen 3
T Socket Server Anwendung - Empfang eines Byte-Arrays Allgemeine Java-Themen 7
J NumberFormatException bei String->byte[] Allgemeine Java-Themen 12
ARadauer Blob aus byte Array erstellen? Allgemeine Java-Themen 3
T Object -> byte[] Allgemeine Java-Themen 5
G Byte[] zeichenweise lesen Allgemeine Java-Themen 4
G byte[] mit Strings füllen Allgemeine Java-Themen 2
B int -> byte Allgemeine Java-Themen 2
G file --> byte[] Allgemeine Java-Themen 7
E Problem beim Dateien kodieren ("Byte = Byte +1") Allgemeine Java-Themen 3
I String -> byte[] -> String Allgemeine Java-Themen 2
D byte nach integer? Allgemeine Java-Themen 4
MQue int in byte Allgemeine Java-Themen 18
G Maximalgröße von byte[] buffer Allgemeine Java-Themen 7
E String -> byte[] Allgemeine Java-Themen 6
C Byte[] to String Allgemeine Java-Themen 7
D datei in byte[]-array schreiben Allgemeine Java-Themen 6
D byte[] problem Allgemeine Java-Themen 3
MQue ArrayList in ein byte- Array Allgemeine Java-Themen 7
B ein spezielles Byte-Array sortieren Allgemeine Java-Themen 11
T OutputStream - Event bei Byte-Fluss Allgemeine Java-Themen 5
J byte-Array in Hashmap speichern? Allgemeine Java-Themen 3
S Problem beim Einlesen von byte-werten aus datei Allgemeine Java-Themen 2
J byte-Array als String übers http schicken Allgemeine Java-Themen 8
F List<String> zu byte[] Allgemeine Java-Themen 7
L byte vs. int Allgemeine Java-Themen 6
G Umwandlung Byte in Integer Allgemeine Java-Themen 12
N Byte-Code entschlüsseln (Bitmasks?) Allgemeine Java-Themen 3
R byte - string? Allgemeine Java-Themen 10
R Stream Byte für Byte durchgehen Allgemeine Java-Themen 5
S java.io.InputStream.read(byte[] b) überschreiben Allgemeine Java-Themen 33
B boolean array = byte array (platzverbrauch) Allgemeine Java-Themen 6
L byte[] to int Allgemeine Java-Themen 2
M Vector zu einem byte[] Allgemeine Java-Themen 5
C Byte Array aus Datei erzeugen Allgemeine Java-Themen 6
T BufferedImage aus einem byte-Array? Allgemeine Java-Themen 2
B Problem mit Einlesen vom Byte FF aus Dateien Allgemeine Java-Themen 5

Ähnliche Java Themen

Neue Themen


Oben