Java Language
ByteBuffer
Recherche…
Introduction
La classe ByteBuffer
été introduite dans java 1.4 pour faciliter le travail sur les données binaires. Il est particulièrement adapté pour être utilisé avec des données de type primitif. Il permet la création, mais aussi la manipulation ultérieure d'un byte[]
s sur un niveau d'abstraction plus élevé
Syntaxe
- octet [] arr = nouvel octet [1000];
- ByteBuffer buffer = ByteBuffer.wrap (arr);
- ByteBuffer buffer = ByteBuffer.allocate (1024);
- ByteBuffer buffer = ByteBuffer.allocateDirect (1024);
- octet b = buffer.get ();
- octet b = buffer.get (10);
- short s = buffer.getShort (10);
- buffer.put ((octet) 120);
- buffer.putChar ('a');
Utilisation de base - Création d'un ByteBuffer
Il existe deux manières de créer un ByteBuffer
, où l’on peut subdiviser à nouveau.
Si vous avez un byte[]
existant byte[]
, vous pouvez l’ emballer dans un ByteBuffer
pour simplifier le traitement:
byte[] reqBuffer = new byte[BUFFER_SIZE];
int readBytes = socketInputStream.read(reqBuffer);
final ByteBuffer reqBufferWrapper = ByteBuffer.wrap(reqBuffer);
Ce serait une possibilité pour le code qui gère les interactions de réseau de bas niveau
Si vous ne disposez pas d'un byte[]
existant byte[]
, vous pouvez créer un ByteBuffer
sur un tableau spécifiquement alloué au tampon, comme ceci:
final ByteBuffer respBuffer = ByteBuffer.allocate(RESPONSE_BUFFER_SIZE);
putResponseData(respBuffer);
socketOutputStream.write(respBuffer.array());
Si le chemin de code est extrêmement critique et que vous avez besoin d' un accès direct à la mémoire du système , le ByteBuffer
peut même allouer des tampons directs à l' aide de #allocateDirect()
Utilisation de base - Écrire des données dans le tampon
Étant donné un ByteBuffer
exemple , on peut écrire des données de type primitif à l'aide relative et absolue put
. La différence frappante est que le fait de mettre des données en utilisant la méthode relative garde la trace de l'index auquel les données sont insérées pour vous, alors que la méthode absolue exige toujours de donner un index pour put
les données.
Les deux méthodes permettent de "chaîner" les appels. Étant donné un tampon de taille suffisante, on peut faire ce qui suit:
buffer.putInt(0xCAFEBABE).putChar('c').putFloat(0.25).putLong(0xDEADBEEFCAFEBABE);
ce qui équivaut à:
buffer.putInt(0xCAFEBABE);
buffer.putChar('c');
buffer.putFloat(0.25);
buffer.putLong(0xDEADBEEFCAFEBABE);
Notez que la méthode fonctionnant sur les byte
n'est pas nommée spécialement. En outre noter qu'il est également valide pour passer à la fois un ByteBuffer
et un byte[]
pour put
. A part cela, tous les types primitifs ont des méthodes de put
spécialisées.
Une note supplémentaire: L'index donné lors de l'utilisation de put*
absolu put*
est toujours compté en byte
s.
Utilisation de base - Utilisation de DirectByteBuffer
DirectByteBuffer
est une implémentation spéciale de ByteBuffer
qui ne comporte aucun byte[]
dessous.
Nous pouvons allouer un tel ByteBuffer en appelant:
ByteBuffer directBuffer = ByteBuffer.allocateDirect(16);
Cette opération allouera 16 octets de mémoire. Le contenu des tampons directs peut résider en dehors du tas normal récupéré.
Nous pouvons vérifier si ByteBuffer est direct en appelant:
directBuffer.isDirect(); // true
Les principales caractéristiques de DirectByteBuffer
sont que JVM essaiera de travailler en mode natif sur la mémoire allouée sans mise en mémoire tampon supplémentaire, de sorte que les opérations effectuées sur celui-ci peuvent être plus rapides que celles effectuées sur ByteBuffer avec des tableaux situés en dessous.
Il est recommandé d'utiliser DirectByteBuffer
avec des opérations d'E / S lourdes reposant sur la vitesse d'exécution, comme la communication en temps réel.
Nous devons être conscients que si nous essayons d'utiliser la méthode array()
, nous obtiendrons une UnsupportedOperationException
. Il est donc recommandé de vérifier si notre ByteBuffer l’a (tableau d’octets) avant d’essayer d’y accéder:
byte[] arrayOfBytes;
if(buffer.hasArray()) {
arrayOfBytes = buffer.array();
}
Une autre utilisation du tampon d'octet direct est l'interopérabilité via JNI. Comme un tampon d'octet direct n'utilise pas d' byte[]
, mais un bloc de mémoire réel, il est possible d'accéder à cette mémoire directement via un pointeur en code natif. Cela permet d’économiser un peu de temps et d’encombrement lors de la répartition entre Java et la représentation native des données.
L'interface JNI définit plusieurs fonctions pour gérer les tampons d'octets directs: Support NIO .