# Umwandlung Byte in Integer



## gizmo (14. Dez 2006)

Ich habe eine Klasse geschrieben, welche Aufgrund von Magic Numbers den Mime Type einer Datei herausfindet. Dazu musste ich die ersten Bytes der Datei einlesen und in einen HEX-String umwandeln. Die Umwandlung funktioniert so:
	
	
	
	





```
for(int i = 0; i < tempBytes.length; i++) {
tempStringBuffer.append(Integer.toHexString(tempBytes[i] & 0xFF));
}
```
Die Variante mit dem & 0xFF habe ich im Netz gefunden. Leider verstehe ich sie nicht. Vielleicht kann es mir jemand erklären.


----------



## Leroy42 (14. Dez 2006)

```
tempBytes[i] & 0xFF
```

Nennt man _maskieren_.

Der Wert von von tempBytes[ i ], der im Computer
grundsätzlich im sogenannten 2-er Komplement
dargestellt wird, wird mit der Bitmaske
0xFF = 1111 11112 = 26510 via UND verknüpft, so daß nur
die Bits _überleben_ (also vom ursprünglichen Wert gesetzt bleiben),
die auch auf "1" stehen. Anders gesagt: Es wird nur der Wert 
von tempBytes modulo 256 geliefert.

Und nochmal anders gesagt: Es wird nur das LSB (_lowest signifikant byte_) des
Ursprungswerts geliefert.

Alle Klarheiten beseitigt?


----------



## gizmo (14. Dez 2006)

Leroy42 hat gesagt.:
			
		

> Alle Klarheiten beseitigt?


Ja, meintest du nicht 256 und wären es nicht 255?

Aber verstanden habe ich das Ganze leider noch nicht...


----------



## SlaterB (15. Dez 2006)

> Anders gesagt: Es wird nur der Wert von tempBytes modulo 256 geliefert. 

das sagt doch alles,
wenn du nun modulo nicht kennst, dann kann man weiterreden,
aber so ist das doch ausreichend erklärt

wenn tempBytes_ ein Byte ist, dann scheint mir diese Operation unnötog,
aber einen großen Integer kriegt man so klein_


----------



## Ark (15. Dez 2006)

Bei einer *ganzzahligen Division* bilden zwei Werte das Ergebnis:

Der *größere Teil* ist der, der bei einer Division mit gebrochenen Zahlen dem Teil _vor_ dem Komma entspricht.

Der *kleinere Teil* ist der, der bei einer Division mit gebrochenen Zahlen dem Teil _nach_ dem Komma entspricht. Das ist der *Rest (Modulo)*. Dieser Rest wächst nicht zwingend mit dem Dividenden, sondern dreht sich im Kreis, nimmt dabei nur Werte an, die zwischen 0 und exklusive dem Divisor liegen:

Dividend : Divisor = Ganzzahlquotient Rest Modulo
0 : 7 = 0 Rest 0
1 : 7 = 0 Rest 1
2 : 7 = 0 Rest 2
3 : 7 = 0 Rest 3
4 : 7 = 0 Rest 4
5 : 7 = 0 Rest 5
6 : 7 = 0 Rest 6
7 : 7 = 1 Rest 0
8 : 7 = 1 Rest 1
9 : 7 = 1 Rest 2
10 : 7 = 1 Rest 3
11 : 7 = 1 Rest 4
12 : 7 = 1 Rest 5
13 : 7 = 1 Rest 6
14 : 7 = 2 Rest 0
15 : 7 = 2 Rest 1
…

Dieser Rest funktioniert quasi wie ein Kilometerzähler: Wenn die Anzahl der gefahrenen Kilometer die Darstellungsmöglichkeiten des Kilometerzählers übersteigt, dann wird der obere *(größere) Teil* _einfach abgeschnitten_.

Bei der Maskierung funktioniert das ganz genauso: Die oberen *(„größeren“)* Bits (hier: mit Wertigkeiten über 255, also 256 und aufwärts) werden einfach durch die UND-Verknüpfung ausgeschaltet, abgeschnitten. Das funktioniert allerdings nur, wenn der Divisor eine Zweierpotenz (1, 2, 4, 8, 16, 32, …) ist, in unserem Fall 256. Die Maske hat hier übrigens immer den Wert des Divisors minus eins (also z. B. 255), gibt quasi den Maximalwert an. (Nach einer UND-Verknüpfung von A und B ist das Ergebnis nie größer als A und auch nie größer als B.)

Jetzt alle Klarheiten beseitigt!? 

Ark


----------



## gizmo (16. Dez 2006)

Ja, das habe ich soweit verstanden. Wie werden denn Byte und Integer intern dargestellt?
	
	
	
	





```
System.out.println(0xFF);
		System.out.println((byte)0xFF);
		System.out.println((int)0xFF);
		System.out.println((byte)0xFF & 0xFF);
		System.out.println((byte)(0xFF & 0xFF));
		System.out.println((int)(0xFF & 0xFF));
```
Ergibt:
	
	
	
	





```
255
-1
255
255
-1
255
```


----------



## Leroy42 (16. Dez 2006)

gizmo hat gesagt.:
			
		

> Wie werden denn Byte und Integer intern dargestellt?



Wie ich bereits geschrieben habe: Im sogenannten 2-er Komplement

Deine _merkwürdigen_ Ausgaben rühren daher, daß in Java sogar
der Typ _byte_ signed ist. Ist also das höchstwertige Bit (Bit 8) in einem
Byte gesetzt, wird das Byte als negativ angesehen.
Wertebereich eines Byte in Java : [-128..127]

Das und das es überhaupt kein unsigned Byte in Java gibt,
halte ich persönlich für eine Entwurfsschwäche der SUNisten.


----------



## byte (16. Dez 2006)

Ich halte das nicht für eine Schwäche. Ein Byte ist erstmal ein Byte, also eine Folge von 8 Bit. Der Rest ist einfach eine Frage der Interpretation. Wenn ich ein Byte ausgebe, dann wird es als signed interpretiert, also mit einem Vorzeichen-Bit. Wenn ich das Byte unsigned interpretieren möchte, kann man ja entsprechend maskieren und als int ausgeben. Computer interessiert es nicht, ob der Mensch da ein Bit als Vorzeichen interpretiert oder ein anderes Bit als Hans-Wurst.   Und beim Rechnen mit den Bit-Operatoren ist diese Interpretation der Bits auch egal. Oder gibt es etwas, was Du mit einem Java Byte nicht machen kannst aufgrund dieser Design-Decision?

Ich finds gut, wie es ist, denn so sind alle primitiven Typen einheitlich und unterscheiden sich lediglich in der Größe des Zahlenraums.


----------



## Leroy42 (16. Dez 2006)

byto hat gesagt.:
			
		

> Wenn ich das Byte unsigned interpretieren möchte, kann man ja entsprechend maskieren und als int ausgeben.



Nun ja, wenn ich mit Bits rumwirbeln muß, steh' ich mit dem Java-Byte
etwas auf Kriegsfuß. Liegt aber vielleicht auch nur daran, daß ich mich
persönlich mit dem signed-Byte nicht anfreunden mag.


----------



## byte (16. Dez 2006)

Ja, aber warum denn?  Wer mit rohen Bytes arbeitet, der verwendet eh nur Bitoperatoren (da spielt signed/ unsigned keine Rolle). Und wer arithmetische Operatoren verwendet, der braucht ja auch Vorzeichen.


----------



## tuxedo (3. Aug 2007)

Sorry wenn ich den alten Beitrag nochmal ausgrabe. Aber ich steht vor dem selben Problem wieder Threadstarter und schnalls gerade nicht.

Angenommen ich habe die Zahl 254. Als unsigned Bitfolge sieht das dann so aus:


```
11111110
```

Das habe ich als Byte vorliegen. Java sieht da, ohne die Konvertierung mit "& 0xFF" den Wert "-2". Das hab ich auch schon verstanden warum (Zweierkomplement und so...).

Aber wenn ich jetzt diese Bitfolge mit 0xFF, sprich 11111111, maskiere, dann bin ich doch genau so schlau wie vorher?!

Bsp:


```
_11111110 (die 254)
&11111111 (die Maske 0xFF)
-------------
_11111110 (das Ergebnis)
```

Was hat mir jetzt das maskieren gebracht? Die Bitfolge ist nach wie vor die gleiche. Und weiter hab ich ja das Problem dass ich mit 8 Bits SIGNED gar kein 254 darstellen kann, weil ja der Bereich von -128..127 geht ... Ergo müssten da noch bytes/bits dazu kommen.

Weiter ist bei Wikipedia zu lesen:

http://de.wikipedia.org/wiki/Bitweiser_Operator#UND


> Das bitweise AND kann verwendet werden um eine Bitfolge zu maskieren. Dadurch können Teile eines Bitstrings isoliert werden und man kann bestimmen, ob ein bestimmtes Bit gesetzt ist oder nicht. Beispiel:
> 
> 0011
> 
> ...



D.h. die maskierung macht nur Sinn wenn ich mindestens eine 0 in der Maske habe? Weil sonst bleibt die Bitfolge ja IMMER unverändert?!

*Völligverwirrtbin*

- Alex


----------



## tuxedo (3. Aug 2007)

Ah, ich glaube ich verstehe ...
Ich sollte beim umrechnen mehrere Bytes mir _dazudenken_ ...


```
_________11111110 (wieder 254, noch als 1 byte dargestellt )
&0000000011111111 (0x00FF, exemplarisch mal ein zusätzliches Byte, da wir wissen dass es beim umrechnen Werte geben kann die nichtmehr mit signed-byte (größe 1byte) abzudecken sind.)
-----------------
_0000000011111110
```

So, wenn man das jatzt aus der 2-Byte-Sicht betrachtet, so ist ganz links keine 1 mehr. Ergo ist das ganze wieder eine positive Zahl mit dem Wert 254...
Und wenn man das 0xFF weglässt, würden die hinzukommenden bytes beim casten nach Integer oder sonstwas (short, ...) wieder dazu kommen, womit dann die ganze Bitfolge links mit 1 aufgefüllt wäre, was wieder eine negative Zahl ergeben würde.

Hab ich das richtig "interpretiert" ?

- Alex


----------



## tuxedo (3. Aug 2007)

Ich hab mal in Java ein wenig gebastelt. Glaube meine Vermutung war richtig:


```
System.out.println(0xfe); // 254
System.out.println(0xff); // 255
System.out.println(0x00ff); // 255
System.out.println(0xfffe); // 65534
		
System.out.println("-----");
		
System.out.println((byte) 0xfe);
System.out.println((byte) 0xfffe);
System.out.println((int)   ((byte) 0xfe   & 0xff  ));
System.out.println((int)   ((byte) 0xfffe & 0x00ff));
System.out.println((int)   ((byte) 0xfffe & 0xff  ));
```

ergibt


```
254
255
255
65534
-----
-2
-2
254
254
254
```

Ergo: Mit "& 0xFF" wird nicht nur das einzelne byte das konvertiert werden soll maskiert, sondern auch die noch folgenden bytes für den Ziel-Datentyp ...


----------

