Hex Strings in Hex array

huckleberry

Bekanntes Mitglied
Hallo,

ich habe HEX Strings, etwa: "0123456789ABCDEF"

Diese würde ich gerne in ein byte [] Packen:

Java:
payload = new byte[]{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};

Für Elemente größer als 127 bekomme ich ein:
Type mismatch: cannot convert from int to byte

Ich würde gerne binär arbeiten und verstehe die Meldung nicht.

Bin dankbar für hinweise..

MfG Huck
 
byte geht aber auch ins negative, 256 unterschiedliche Werte von 00 bis FF kann man schon darstellen,
auf (byte) casten und evtl. vorher -128 rechnen
 
byte geht aber auch ins negative, 256 unterschiedliche Werte von 00 bis FF kann man schon darstellen,
auf (byte) casten und evtl. vorher -128 rechnen

Falls es huckleberry nicht klar ist:
Nicht "EVTL.", sondern "IMMER" davor "-128" (=0x80) rechnen, wenn auch nur 1 Wert über 0x7F / 127 möglich sein soll!
Sonst weißt du nachher nie ob z.B. 0x03 nun eine 3 oder 3+128=131 sein soll.
 
kommt darauf an, wie man die Verteilung haben will,
rechnet man nicht -128, dann werden die großen Zahlen automatisch ins negative geschoben,
Java:
public class Test
{
    public static void main(String[] args)
    {
        for (int i = 0; i < 256; i++)
        {
            System.out.println("i: " + i + ", " + ((byte)i) + ", " + ((byte)(i - 128)));
        }
    }
}

die rechte Reihe hier, mit -128, ist aber sicher die schönere
 
Funktioniert ein cast (byte)(217)?
Dann müsste der cast (byte)(217) == (byte)(-39) das selbe ergeben?!
Wenn's so ist, dann kann man sich -128 wohl sparen.
(Ich hab ich nie getestet, und war der Meinung, es müsste craschen.
Lerne aber gerne dazu.)

Dann stellt sich nur noch für Ausgabe die Frage, wie das eigentliche Problem am elegantesten umgesetzt werden kann:
ich habe HEX Strings, etwa: "0123456789ABCDEF"

------------------------
Edit:
Slater macht ja schön vor, wie die WerteListe aussehen kann.
 
Zuletzt bearbeitet:
Java:
byte b = (byte)(129);
int unsignedByte = b & 0xff;		
System.out.println(unsignedByte);   // 129
System.out.println(b);                    // -127
 
gewagte differenzierende Anerkennung,
nachdem du dich vorher mit mir unterhalten hast und ich auch
System.out.println()
kodiert hatte 😉
von Ausgabe als Kommentar direkt dahinter sagt deine Signatur nichts 😉
 
Sorry, Slater!

War eigentlich als Kritik an mich selbst gerichtet:
Ich @michselbst: probiers doch aus, statt lang zu rätseln! Du Dödl!

Ich wollte deinen Beitrag nicht minder schätzen!
 
Kann mir bei der Gelegenheit jemand erklären, wozu dieser "dirty hack" gut sein soll? Ich dachte, die JVM rechnet intern sowieso mit mindestens 4 Byte langen Werten - egal ob byte, short oder eben int.
 
was soll denn ein hack sein? Daten als byte 'zu haben' ist schon ein wichtiger Schritt allgemein,
wenn man sie an Streams schicken will oder was auch immer,
hier von String aus zwingender Schritt, auch bei int wie man sieht nicht ganz ohne,
wobei man theoretisch mit int gut im byte-Bereich arbeiten könnte

OutputStream hat dann auch eine Methode write(int b)
Writes the specified byte to this output stream. The general contract for write is that one byte is written to the output stream.
The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.
 
Java hat nunmal keine "unsigned bytes" - insofern erscheint mir der Versuch, Werte größer 127 in ein byte speichern zu wollen, als kein sonderlich guter Stil, der sich leicht vermeiden liese, indem man sofort ints nimmt. Und meines Wissens nach - siehe obiger Beitrag - besitzen bytes keine Vorteile gegenüber ints.
 
nun, bytes haben den famosen Vorteil, dass alle Computer der Welt danach ihr Fähnchen hängen,

wenn du eine Datei lesen/ schreiben bzw. dich irgendwie außerhalb des Java-Sandkasten-abgeschlossen-Arbeitsspeicher bewegst,
musst du dich schlicht danach richten, mag mehr Notwendigkeit als Vorteil sein,
 
Ok, ich habe mich wohl undeutlich ausgedrückt. Also nochmal:

Mir ist es völlig wurscht, ob die JVM die Elemente als signed, unsigned, 4 Kilo Äpfel oder eine Sahnetorte interpretiert. Wenn ich ein 0xFF in ein byte [] reinschiebe, dann soll dort 0xFF stehen und ich möchte keine Fehlermeldung.

Also muss ich einzelne Elemente casten:
Java:
payload = new byte[]{0x10, 0x09, 0x2E, (byte) 0xF1, (byte) 0x98, 0x03, (byte) 0x86, (byte) 0xC1};
Solange sich der Hex-Wert nicht ändert passt das.
 
es sollte dich schon interessieren, welchen Wertebereich byte hat und ob die Werte durch das Casten geändert werden..,
naja, wenn es wichtig ist wird es irgendwann schon auffallen

falls dir deine Codezeile zuviel Schreibarbeit ist und noch öfter ähnliches kommt, könntest du dir eine Methode mit int... als beliebig langen Parameter definieren, intern ein byte[] erstellen und zurückgeben,
dann sieht es so aus:

Java:
payload = make(0x10, 0x09, 0x2E, 0xF1, 0x45980, -42, .. );
die Methode könnte auch prüfen, ob die Einzelwerte zumindest zwischen 0 und 255 liegen, egal wie dann auf byte abgebildet,
und für andere ne Fehlermeldung ausgeben
 
Wenn du gesichert für "00" den Wert 0x00 in deinem Feld haben willst, und für "FF" den Wert 0xff =255d, dann musst du doch ein bisschen Grips reinstecken (ein bisschen).

Denn es ist eine Ding 255 Werte (irgendwie) eindeutig zu codieren, aber es ist ganz anderes Ding das identische BitMuster im Byte zu erzwingen. (Ohne Fallunterscheidung gehts nicht)

Aber du schaffst das schon, beschäftige dich mal mit den 2er-Kompliment:
0x0000 => 0 => 0x00 => 0
0x0001 => 1 => 0x01 => 1
...
0x007F => 127 => 0x7F => 127
0x0080 => 128 => 0x80 => -128 !!!
0x0081 => 129 => 0x81 => -127 !!!
...
0x00FE => 254 => 0xFE => -2
0x00FF => 255 => 0xFF => -1
0x0100 => 256 => 0x00 => oops, oor
 
Wenn ich ein 0xFF in ein byte [] reinschiebe, dann soll dort 0xFF stehen und ich möchte keine Fehlermeldung.
Das geht in Java aber nicht; eine Variable vom Typ byte kann nicht den Wert 255 enthalten. Du kannst dir lediglich - wie SlaterB vorgeschlagen hat - eine (bijektive!) Funktion schreiben, die dir Integer-Werte im Bereich 0 bis 255 auf eine Variable vom Typ byte abbildet.
Sinnigerweise solltest du aber dann aber auch die dazu inverse Funktion haben, um mit den Werten weiterarbeiten zu können.

Java:
public class Demo {
	public static void main (String[] args) {
		int[] payloadInt = new int[]{0x10, 0x09, 0x2E, 0xF1, 0x98, 0x03, 0x86, 0xC1};
		byte[] payloadByte = intToByte(payloadInt);
		
		for (int i: payloadInt)
			System.out.print(Integer.toHexString(i) + " ");
		System.out.println();
		
		for (int i: byteToInt(payloadByte))
			System.out.print(Integer.toHexString(i) + " ");
		System.out.println();		
	}
	
	public static byte[] intToByte(int[] intArray) {
		byte[] byteArray = new byte[intArray.length];
		for (int i=0; i<intArray.length; i++)
			if (0 <= intArray[i] && intArray[i] <= 255)
				byteArray[i] = (byte) intArray[i];
			else
				throw new IllegalStateException("foo");
		return byteArray;
	}
	
	public static int[] byteToInt(byte[] byteArray) {
		int[] intArray = new int[byteArray.length];
		for (int i=0; i<byteArray.length; i++)
			intArray[i] = byteArray[i] & 0xff;
		return intArray;
	}
}

Das bliebe dir allerdings erspart, wenn du von Anfang an ein int-Array verwenden würdest.
Java:
int[] payload = new int[]{0x10, 0x09, 0x2E, 0xF1, 0x98, 0x03, 0x86, 0xC1};


@AquaBall:
Die Bitmuster sind doch im Zweierkomplement bereits ident.
Als int: 0xFF = 255 (d) = 1111 1111 (b)
Nach einem Cast zum Byte: -1 (d) = 1111 1111 (b)
Nur die Interpretation ist eine andere, da sich das MSB ändert. Bei der ersten Ziffernfolge wäre das MSB 0 (da die ersten 24 Stellen mit Nullen aufgefüllt sind), also wird die Zahl als positive Zahl interpretiert. Die zweite Zahl hat nur acht Stellen (da vom Typ Byte), d. h. die erste Stelle ist eine 1 und wird folglich als negative Zahl interpretiert. Aber die Bitmuster sind - wenn man sich auf die letzten acht Stellen beschränkt - jeweils die gleichen.
 
Die Bitmuster sind doch im Zweierkomplement bereits ident.
Als int: 0xFF = 255 (d) = 1111 1111 (b)
Nach einem Cast zum Byte: -1 (d) = 1111 1111 (b)
Nur die Interpretation ist eine andere, da sich das MSB ändert.

Genau das mein' ich auch: Wenn er die Daten wieder lesen will (Wozu sonst speichern), dann kommt er um eine Fallunterscheidung nicht herum, weil sich die Interpretation ändert.
 

Zurück
Oben