# Umgang mit ByteBuffer



## i.b.fan (28. Apr 2010)

Hallo zusammen, 

leider bin ich auf der Suche nach einer für mich verständlichen (umfangreichen) Beschreibung der Klasse ByteBuffer verzweifelt. Beim Experimentieren dann (trial & error), bin ich auf unlösbare Probleme gestoßen, die entweder Anfängerfehler oder Verständnisprobleme sind, bei denen Ihr mir bestimmt mit müdem Lächeln weiterhelfen könnt.

Mein Gedanke: 
Ich lese eine Datei in ein byte-Array zu 50 Zeilen mit jeweils 20 Zeichen (fest). Nun habe ich als Ergebnis ein zweidimensionales Array. Das funktioniert auch soweit.

Nun ist aber das Arbeiten mit diesem Array sehr umständlich, was mich auf die Klasse ByteBuffer brachte, da man mit ihr je nach Belieben den Inhalt des Arrays interpretieren und bearbeiten kann.

Und jetzt meine Probleme:
Ich bräuchte dann ja ein ByteBuffer-Array für die 50 Zeilen mit einer Länge von jeweils 20. Ich kriege es aber nicht hin, dies zu initialisieren. Meinem Verständnis nach müsste das ja so, oder so ähnlich gehen:


```
ByteBuffer[] byteBuf = new ByteBuffer[zeilenAnzahl].allocate(zeichenAnzahl);
```

Oder gehen Arrays schon garnicht mit dem ByteBuffer?

Und brauche ich denn zwingend ein Byte-Array "darunter" bzw. als Zwischenschritt? Dann wäre es ja "nur" eine Ansicht der Datenmenge, was ja auch ok wäre. Nur warum gibt es dann noch die Views in ByteBuffer? 

Ich hätte ja im Umkehrschluss gedacht, man lade eine Zeile in einen ByteBuffer (ohne Array) und nutze dann die Views, um sich den Inhalt mal als short, mal als char, mal als int anzeigen zu lassen. Und insbesondere interessiert mich die Möglichkeit, die ByteOrder einfach zu wechseln.

Liege ich da komplett falsch, oder hapert es nur an meiner Umsetzung? ???:L

Bin Euch für jede Erklärung, Tipp oder Link dankbar! 

i.b.fan


----------



## SlaterB (28. Apr 2010)

ein ByteBuffer-Array ist vor allem nur ein Array, nix anderes, da kann man ein Element abfragen und die Länge, mehr nicht,
die allocate()-Methode gehört wenn überhaupt an einen ByteBuffer, hat mit dem dem ByteBuffer-Array nix zu tun,

ByteBuffer b = array[37];
b.wasauchimmer();


---

allocate scheint gar eine statische Methode zu sein, die ein ByteBuffer-Objekt erstellt, was hat das mit dem Array zu tun?
eine Zuweisung könnte Sinn ergeben:

array[9] = ein passendes Objekt
array[9] = ByteBuffer.allocate(xy); // erstellt ein passendes Objekt

---

versuche doch erstmal ohne Array nur eine Zeile zu bearbeiten


----------



## Murray (28. Apr 2010)

Wenn du aus einen gegebenen Byte-Array einen ByteBuffer machen willst, dann ist statt allocate vermutlich wrap die bessere Wahl.


----------



## i.b.fan (28. Apr 2010)

Hallo SlaterB,

bisher habe ich das (einzeilig) so hinbekommen:

```
ByteBuffer buffer = ByteBuffer.allocate(20);
```

oder mit schon vorhandenem byte-Array (eindimensional Zeile 13) so:

```
ByteBuffer buffer = ByteBuffer.wrap(byteArray[13]);
```

Nur will ich ja nicht 50mal die o.g. Zeile eingeben und buffer1, buffer2 etc. erzeugen. 
Aber wahrscheinlich liegt da schon mein Verständnisproblem....

"array[9] = ein passendes Objekt" 
Ist das ein Objekt? Dachte, das wäre eine "Ansammlung" primitiver Daten *kopfkratz*


----------



## Murray (28. Apr 2010)

Ist byteBuffer ein byte[][]?

 Dan müsste es doch so gehen

```
ByteBuffer[] buffer = new ByteBuffer[ byteArray.length];
for ( int i=0; i<byteArray.length; i++) {
  buffer[i] = ByteBuffer.wrap( byteArray[i]);
}
```


----------



## i.b.fan (28. Apr 2010)

Murray hat gesagt.:


> Wenn du aus einen gegebenen Byte-Array einen ByteBuffer machen willst, dann ist statt allocate vermutlich wrap die bessere Wahl.



Hallo Murray,

so habe ich es ja auch hinbekommen. Und dies dann auch durch eine for-Schleife wiederholen, nur eigentlich brauche ich das byte-Array nicht, wenn ich das mit ByteBuffer allein machen kann. Drum hielt ich es für "gemauschelt" erst ein byte-Array zu erzeugen, nur weil ichs anders nicht hinkrieg 

Aber vielleicht geht es ja nur so (darauf bezog sich der hintere Teil meiner Anfrage)


----------



## i.b.fan (28. Apr 2010)

Murray hat gesagt.:


> Ist byteBuffer ein byte[][]?


Nein, byteBuffer soll ein ByteBuffer[] sein, der den Inhalt von byteArray[][] repräsentiert. byteArray ist ein byte[][].

Das mit der for-Schleife hatte ich auch gedacht, hatte der Compiler aber auch immer wieder angemahnt. Nur hab ich inzwischen so viel probiert, dass ich nicht mehr genau weiss, was. Ich probier das morgen nochmal und poste dann den konkreten Fehler.

Danke schonmal und gute Nacht!


----------



## Murray (28. Apr 2010)

i.b.fan hat gesagt.:


> Nein, byteBuffer soll ein ByteBuffer[] sein, der den Inhalt von byteArray[][] repräsentiert. byteArray ist ein byte[][].


Sorry, da habe ich gepennt - ich wollte eigentlich wissen, ob byteArray ein zweidimensionales Array ist (davon geht der gepostete Vorschlag aus); das hast du jetzt ja beantwortet.

Prinzipiell müsste es also gehen; mal sehen, was der Compiler bei dir noch auszusetzen hat


----------



## i.b.fan (28. Apr 2010)

Hallo nochmals,

nun habe ich systematisch die Versuche zusammengefasst und inzwischen das ein oder andere zumindest im Ansatz verstanden 
Immerhin bekomme ich mit *testSieben *wohl ein ByteBuffer-Array hin, aber warum der mir eine Warnung ausgibt, verstehe ich nicht. Und so ganz, warum das dann so geht, und andersrum nicht, erschliesst sich mir auch noch nicht... :bahnhof:
Immer wenn ich denke, ein "hä?!" ausgeräumt zu haben, kommt ein "hääääääää?!?" hinzu 
Kann mich jemand aufklären? 


```
package bytebuffertest;

import java.nio.ByteBuffer;

public class Main {

    public static void main(String[] args) {

        byte[][] byteArray = { {0x00, 0x01, 0x02, 0x03, 0x04},
                               {0x05, 0x06, 0x07, 0x08, 0x09},
                               {0x0a, 0x0b, 0x0c, 0x0d, 0x0e}  };


        ByteBuffer testEins = ByteBuffer.allocate(5);         //keine Fehler
        testEins.put(byteArray[1]);

        //inzwischen glaube ich auch zu verstehen, warum Folgendes nicht geht:
        //ByteBuffer testZwei = new ByteBuffer.allocate(5);
        //Ausgabe: cannot find symbol class allocate (wäre innere Klasse, oder?)
        
        //ByteBuffer testDrei = new ByteBuffer();
        //Ausgabe: ByteBuffer is abstract; cannot be instantiated
        //(geht nur über die static Methoden, welche aber ein Objekt erzeugen)

        ByteBuffer testVier = ByteBuffer.wrap(byteArray[1]);  //keine Fehler

        ByteBuffer[] testFünf = new ByteBuffer[3];            //keine Fehler
        //for(int i=0; i<3; i++){
        //   testFünf[i].put(byteArray[i]); //zur Laufzeit: NullPointerException
        //}

        ByteBuffer[] testSechs = new ByteBuffer[3];            //keine Fehler
        //for(int i=0; i<3; i++){
        //   testSechs[i].allocate(5);  //warning: accessing static method
        //   testSechs[i].put(byteArray[i]);//zur Laufzeit: NullPointerException
        //}

        ByteBuffer[] testSieben = new ByteBuffer[3];
        for(int i=0; i<3; i++){
            testSieben[i].wrap(byteArray[i]); //warning: accessing static method
        }                                                //KEIN Laufzeitfehler!!! *freu*

    }

}
```


----------



## i.b.fan (28. Apr 2010)

Murray hat gesagt.:


> Ist byteBuffer ein byte[][]?
> 
> Dan müsste es doch so gehen
> 
> ...


Hallo Murray,

so geht es tatsächlich, danke! (s. testSieben im vorigen Post)!
Allerdings gibt mir der Compiler die Warnung aus, dass ich eine statische Methode aufrufe...


----------



## Murray (29. Apr 2010)

wrap ist eine statische Methode der Klasse ByteBuffer. Du rufst sie hier an einer Instanz auf - das ist zwar möglich, macht aber nicht, was du willst; daher ist es ganz gut, dass hier die Warnung kommt.

Bei dir steht

```
for(int i=0; i<3; i++){
  testSieben[i].wrap(byteArray[i]);
}
```

Wollte man die Warnung loswerden, müsste man die statische Methode an der Klasse (und nicht an der Instanz) aufrufen:

```
for(int i=0; i<3; i++){
  ByteBuffer.wrap(byteArray[i]);
}
```

Diese Code ist äquivalent zum ersten!! Man sieht: durch die Schleife ändert sich an testSieben nichts.

Richtig wäre 

```
for(int i=0; i<3; i++){ //--- noch schoener: statt der hart codierten 3 hier testSieben.length einsetzen
  testSieben[i] = ByteBuffer.wrap(byteArray[i]);
}
```


----------



## i.b.fan (29. Apr 2010)

Murray hat gesagt.:


> ...das ist zwar möglich, macht aber nicht, was du willst; daher ist es ganz gut, dass hier die Warnung kommt.


Ja, das habe ich gemerkt 
Ich bin schon fast verzweifelt, weil ich bei der weitergehenden Verarbeitung immer NullPointerExceptions bekommen habe - und die Testausgabe der Objekte immer "null" war.

Dank Deiner sehr guten Erklärung klappt es jetzt nicht nur, sondern ich hab auch verstanden warum!:toll:

Vielen Dank!

PS: noch zwei kleine Nachfragen: die Funktionen flip() und rewind() werden immer wieder synonym benutzt, aber einen Unterschied muss es doch geben, oder?
Und die Folgefrage: Wenn ich aber konsequent die Funktionen get... set... nur mit Indexen aufrufe, kann mir das doch eigentlich auch egal sein, oder?!


----------

