Input/Output Viele short aus Datei lesen und von Little Endian zu Big Endian umwandeln

Muhaha

Mitglied
Hi, wie kann ich möglichst schnell sehr viele short aus einer Datei auslesen und von Little Endian zu Big Endian umwandeln?

Bis jetzt habe ich es so gemacht:

Code:
short s;
DataInputStream instream = new DataInputStream(new InputStream(...));
for (int i = 0; i < g; i++) {
	s = instream.readShort();
	sounds[j] = (short) (((((s & 0xff) << 8) | ((s >> 8) & 0xff)) << 16) >> 16);
}

Gibt es eine schnellere Methode?
 
Weis nicht ob es schneller geht, aber über ByteBuffer:
Java:
InputStream in=...;
byte[] tmp=new byte[in.available()];
in.read(tmp);
ByteBuffer byteBuf=ByteBuffer.wrap(tmp);
byteBuf.order(ByteOrder.LITTLE_ENDIAN);
sounds=byteBuf.asShortBuffer().getArray();

Auserdem kann man bei einem ObjektInputStream afaik die ByteOrder auch einstellen.
 
Danke erstmal.

Das Problem bei der Lösung mit dem ShortBuffer/ByteBuffer ist, dass man die Methode shortBuffer.array() nur nutzen kann, wenn man den ShortBuffer nicht aus einem ByteBuffer erzeugt hat.
 
shortBuffer.array() liefert nur einen Array, wenn der Buffer mit ShortBuffer.wrap(shortArray); erzeugt wurde. (Abgesehen davon: 'nativ' ist alles, was erstmal durch den JIT gelaufen ist 😉 )

Ob es gut oder sinnvoll ist, ALLE Daten einzulesen, weiß ich nicht. Aber grundsätzlich kann man natürlich auch mit einem Chunk arbeiten. Also als letzte Zeile von dem, was Kevin94 gepostet hatte, dann eben
shortBuffer.get(shortArray);
um die Daten in den Array zu schreiben. Oder gleich die Datei als MemoryMapped file (über FileChannel) mappen, dann spart man sich den Umweg über den byte[] array.
 
Selbst wenn die Methode array() nicht verfügbar ist, dürfte folgendes immer noch übersichtlicher und vermutlich auch schneller sein:
Java:
ShortBuffer buf=byteBuf.asShortBuffer();
sounds=new short[buf.capacity()];
buf.get(sounds);
 
Selbst wenn die Methode array() nicht verfügbar ist, dürfte folgendes immer noch übersichtlicher und vermutlich auch schneller sein:
Java:
ShortBuffer buf=byteBuf.asShortBuffer();
sounds=new short[buf.capacity()];
buf.get(sounds);
Das wollte ich eigendlich nicht machen, da ich so ja zu einen Zeitpunkt das doppelt an Speicher benötige und der Code auf einem Smartphone laufen soll.

Wenn ich immer nur einen Teil der Datei lese und bearbeite, wieviel sollte ich da aufeinmal laden? Ich dachte mir, am Anfang, dass ich immer soviel lade wie available() zurückgibt, aber in der JavaDoc zu der Methode steht, dass man sich darauf nicht verlassen kann.
 
Wenn es und Sounds geht, ist das so eine Sache - die müssen ja auch irgendwo verarbeitet werden, und das geht prinzipbedingt nicht unendlich schnell, sondern ohnehin nur in der Geschwindigkeit, mit der sie absgespielt werden.
 
Das wollte ich eigendlich nicht machen, da ich so ja zu einen Zeitpunkt das doppelt an Speicher benötige...
[STRIKE]Das ist nicht ganz richtig.[/STRIKE] Von einem ShortBuffer wirst du kein short-Array bekommen (eher 'ne UnsupportedOperationException), solange du ihn per ByteBuffer erstellst (egal ob direct oder nicht). Das Array bleibt stets das per wrap übergebene byte-Array oder gar keines, wenns ein DirectBuffer ist. Speicher wird also nur einmal "verschwendet".
Das short-Array benötigst du ja auch nicht. Du liest und schreibst die Daten mittels der ShortBuffer-Methoden "get(int index)" und "put(int index)". Der unter dem ShortBuffer liegende ByteBuffer wird die Daten dann schon sorgenfrei korrekt in das byte-Array eintragen.
Was man nicht machen sollte ist allerdings es beim ByteBuffer zu belassen und get- bzw. putShort zu verwenden, sonst ist man ewig dabei, die Indices korrekt zu berechnen.
Alles in allem... Buffer sind im allgemeinen ebenso schnell wie normale Arrays und der händischen Berechnung der Datenreihenfolge und Indices. Kurz gesagt, Buffer sind die besseren Arrays.
[EDIT]...von wegen nicht ganz richtig... Absolut korrekt, müsste man sagen. Zumindest bei dem, wie es Kevin94 vorschlägt.[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

Neue Themen


Zurück
Oben