devstory

Le Tutoriel de Java Buffer

View more Tutorials:

Suivez-nous sur notre fanpage pour recevoir des notifications chaque fois qu'il y a de nouveaux articles. Facebook

1- Buffer

Java NIO Buffer représente un conteneur avec une capacité fixe pour stocker des données primitives. Il est souvent utilisé en conjonction avec Java NIO Channel(s). Plus précisément, les données seront lues à partir du Channel dans le Buffer ou écriront des données du Buffer dans le Channel.

public abstract class Buffer extends Object
La hiérarchie des classes et interfaces liées à Java NIO Buffer:
  • ByteBuffer
  • ByteOrder
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • MappedByteBuffer
  • ShortBuffer
La relation entre le Channel et le Buffer est similaire à la celle entre un bol et une cuillère. La cuillère peut être utilisée comme un petit récipient pour prendre le sucre du bol et elle peut également être utilisée comme un petit récipient pour mettre le sucre de l'extérieur dans le bol. Donc, la cuillère équivaut à un Buffer et le bol un Channel.
Capacity, limit, position et mark sont les 4 termes les plus importants de Java NIO Buffer, ils seront expliqués en détail ci-dessous. Dans les deux modes de lecture et d'écriture, le curseur se déplace toujours vers la droite.

2- Buffer Methods


public final int capacity()
 
public final int position()   
public Buffer position(int newPosition)  

public final int limit()   
public Buffer limit(int newLimit)

public Buffer mark()
public Buffer reset()  
public Buffer clear()  
public Buffer flip()   
public Buffer rewind()  

public final int remaining()
public final boolean hasRemaining()

public abstract boolean isReadOnly();
public abstract boolean hasArray();
public abstract Object array();
public abstract int arrayOffset();
public abstract boolean isDirect();
public abstract Buffer slice();
public abstract Buffer duplicate();

3- capacity()


public final int capacity()
La méthode capacity() renvoie la capacité (capacity) de ce Buffer.
Bien que vous ne puissiez lire ou écrire que sur des éléments de l'index 0 à limit-1, si vous définissez limit = capacity, vous pouvez accéder (lecture, écriture) à tous les éléments du Buffer.

4- position()


public final int position()
Renvoyer la position actuelle du curseur. Les opérations de lecture et d'écriture déplacent le curseur à la fin du Buffer. La valeur renvoyée est toujours inférieure ou égale à la limit.
  • 0 <= mark <= position <= limit <= capacity

5- position(int newPosition)


public Buffer position(int newPosition)
Définir la nouvelle position pour le curseur
  • newPostion doit être supérieur ou égal à 0 et inférieur ou égal à la limit.
  • Si newPosition < mark donc la mark sera suprimée (discard).

6- limit()


public final int limit()
Renvoyer limit (la limite) de ce Buffer.
Buffer ne prend en charge la lecture et l'écriture qu'aux éléments de l'index 0 à limit-1, les autres éléments de l'index limit à capacity-1 sont désactivés. Cependant, vous pouvez définir limit = capacity pour avoir l'accès (lire ou écrire) à tous les éléments du Buffer.
  • 0 <= mark <= position <= limit <= capacity
Dans l'exemple ci-dessous: Un CharBuffer avec capacity = 10, et limit = 7, vous ne pouvez lire et écrire que sur les éléments de l'index de 0 à 6. En cas de violation, une exception sera lancée.
Buffer_limit_ex1.java

// Allocate a character type buffer.
CharBuffer buffer = CharBuffer.allocate(10); // capacity = 10

buffer.limit(7); // limit = 7

String text = "abcdefghij";
System.out.println("Input text: " + text);
System.out.println("Text length: " + text.length()); // 10

for (int i = 0; i < text.length(); i++) {
    char chr = text.charAt(i);
    
    // put character in buffer.
    buffer.put(chr);
    System.out.println(i + ". put: " + chr);
}
Output:

Input text: abcdefghij
Text length: 10
0. put: a
1. put: b
2. put: c
3. put: d
4. put: e
5. put: f
6. put: g
Exception in thread "main" java.nio.BufferOverflowException
    at java.base/java.nio.Buffer.nextPutIndex(Buffer.java:665)
    at java.base/java.nio.HeapCharBuffer.put(HeapCharBuffer.java:199)
    at org.o7planning.buffer.ex.Buffer_limit_ex1.main(Buffer_limit_ex1.java:21)

7- limit(int newLimit)


public Buffer limit(int newLimit)
Définir la nouvelle valeur limit pour ce Buffer. newLimit doit être inférieur à la capacity, sinon IllegalArgumentException sera lancée.
  • Si newLimit < position alors postion sera définie comme newLimit.
  • Si newLimit < mark alors la mark sera supprimée (discard).
Par exemple :
Buffer_limit_newLimit_ex1.java

// Allocate a character type buffer.
CharBuffer buffer = CharBuffer.allocate(10); // capacity = 10

System.out.printf("Buffer capacity: %d%n%n", buffer.capacity()); // 10

buffer.limit(9); // limit = 9
System.out.printf("Buffer limit: %d, position: %d%n%n", buffer.limit(), buffer.position());

System.out.println("Set newPostion: 8");
buffer.position(8);

System.out.printf("Buffer limit: %d, position: %d%n%n", buffer.limit(), buffer.position());

System.out.println("Set newLimit: 7");
// Set limit = 7.
buffer.limit(7);

System.out.printf("Buffer limit: %d, position: %d%n", buffer.limit(), buffer.position());
Output:

Buffer capacity: 10

Buffer limit: 9, position: 0

Set newPostion: 8
Buffer limit: 9, position: 8

Set newLimit: 7
Buffer limit: 7, position: 7

8- mark()


public Buffer mark()
La méthode mark() est utilisée pour marquer la position actuelle du curseur. Dans le processus de manipulation de Buffer, la position du curseur peut changer, la convocation de la méthode reset() aidera le curseur à revenir à la position précédemment marquée.
  • 0 <= mark <= position <= limit <= capacity
La mark sera supprimée (discard) dans les cas suivants :
  • Convoquer la méthode setPosition(newPosition) avec newPosition < mark.
  • Convoquer la méthode setLimit(newLimit) avec newLimit < mark.
  • Convoquer la méthode clear(), rewind() ou flip().

9- reset()


public Buffer reset()
La méthode reset() est utilisée pour renvoyer le curseur à la position précédemment marquée. (Voir la méthode mark()).
Cette méthode peut lancer une InvalidMarkException si la mark n'est pas définie ou a été supprimée (discard).
La mark sera supprimée (discard) dans les cas suivants :
  • Convoquer la méthode setPosition(newPosition) avec newPosition < mark.
  • Convoquer la méthode setLimit(newLimit) avec newLimit < mark.
  • Convoquer la méthode clear(), rewind() ou flip().
Par exemple :
Buffer_reset_ex1.java

CharBuffer buffer = CharBuffer.allocate(10); // capacity = 10

System.out.println("Set newPostion: 5");
buffer.position(5);

System.out.println("Mark current position!");
buffer.mark(); // marked position = 5

System.out.println("Call buffer.get() twice!");
char ch1 = buffer.get();
char ch2 = buffer.get();

System.out.printf("Position: %d%n%n", buffer.position()); // position = 7

System.out.println("Reset!");
buffer.reset();

System.out.printf("Position: %d%n%n", buffer.position()); // position = 5
Output:

Set newPostion: 5
Mark current position!
Call buffer.get() twice!
Position: 7

Reset!
Position: 5

10- clear()


public Buffer clear()
La méthode clear() définit position = 0; limit = capacity, supprime (discard) la mark et renvoie ce Buffer. La convocation de cette méthode n'affecte pas les données sur Buffer.
Par exemple :
Buffer_clear_ex1.java

CharBuffer buffer = CharBuffer.allocate(7); // capacity = 7

// Write data to buffer:
buffer.put('A');
buffer.put('B');

buffer.position(3); // Set position to 3.
buffer.limit(5); // Set limit to 5.

System.out.printf("buffer, capcity: %d, limit: %d, position: %d%n%n", //
        buffer.capacity(), buffer.limit(), buffer.position());

System.out.println("Clear...");
buffer.clear();

System.out.printf("buffer, capcity: %d, limit: %d, position: %d%n%n", //
        buffer.capacity(), buffer.limit(), buffer.position());

// Read data in buffer:
while (buffer.hasRemaining()) {
    char chr = buffer.get();
    System.out.println(chr + " --> " + (int) chr); // char and code.
}
Output:

buffer, capcity: 7, limit: 5, position: 3

Clear...
buffer, capcity: 7, limit: 7, position: 0

A --> 65
B --> 66
--> 0
--> 0
--> 0
--> 0
--> 0

11- flip()


public Buffer flip()
La méthode flip() définit limit = actuelle position, position = 0 et renvoie ce Buffer et supprime (discard) la mark. (Voir l'illustration ci-dessous).
L'exemple ci-dessous correspond à l'illustration au-dessus :
Buffer_flip_ex1.java

CharBuffer buffer = CharBuffer.allocate(10); // capacity = 10

System.out.printf("Position: %d, Limit: %d, Capacity: %d%n%n",
        buffer.position(), buffer.limit(), buffer.capacity());

System.out.println("Write 3 characters to buffer\n");
for(char ch : new char[] {'A','B','C'}) {
    buffer.put(ch);
}
System.out.printf("Position: %d, Limit: %d, Capacity: %d%n%n",
        buffer.position(), buffer.limit(), buffer.capacity());

System.out.println("Set limit = 7, position = 5\n");
buffer.limit(7);
buffer.position(5);

System.out.printf("Position: %d, Limit: %d, Capacity: %d%n%n",
        buffer.position(), buffer.limit(), buffer.capacity());   

System.out.println(" --- flip() --- \n");
buffer.flip();  

System.out.printf("Position: %d, Limit: %d, Capacity: %d",
        buffer.position(), buffer.limit(), buffer.capacity()); 
Output:

Position: 0, Limit: 10, Capacity: 10

Write 3 characters to buffer

Position: 3, Limit: 10, Capacity: 10

Set limit = 7, position = 5

Position: 5, Limit: 7, Capacity: 10

 --- flip() ---

Position: 0, Limit: 5, Capacity: 10
La méthode flip() est généralement utilisée après avoir terminé d'écrire des données dans le Buffer, ce qui permet de déplacer le curseur vers l'index 0. Prêt à lire des données utiles sur le Buffer. (Voir des illustrations et exemples ci-dessous).
Buffer_flip_ex2.java

CharBuffer buffer = CharBuffer.allocate(5); // capacity = 5  

// WRITE MODE:
System.out.println("Write 3 characters to buffer\n");
for(char ch : new char[] {'A','B','C'}) {
    buffer.put(ch);
}  
// (Now position = 3, limit = 5, capacity = 5).
System.out.println(" --- flip() --- \n");
buffer.flip();

// READ MODE:
// (Now position = 0, limit = 3, capacity = 5).
while(buffer.position() < buffer.limit()) {
   char ch = buffer.get();
   System.out.println(ch);
} 
Output:

Write 3 characters to buffer

 --- flip() ---

A
B
C

12- rewind()


public Buffer rewind()
La méthode rewind() est utilisée pour rembobiner ce Buffer, en d'autres termes, elle définit position = 0, et supprime (discard) la mark.

13- remaining()


public final int remaining()
Renvoyer le nombre d'éléments entre position et limit-1.

14- hasRemaining()


public final boolean hasRemaining()
Renvoyer true s'il y a des éléments entre position et limit-1. Sinon, renvoyer false.

15- slice()


public abstract Buffer slice();
Renvoyer un nouveau Buffer qui est un cliché partiel de ce Buffer. Le nouveau Buffer inclut les éléments entre la position et la limit-1 de ce Buffer. La position marquée du nouveau Buffer n'est pas définie, la position du nouveau Buffer est 0. (Voir l'illustration ci-dessous).
Ces deux Buffer sont liés l'un à l'autre, les changements de données sur l'un seront visibles sur l'autre et vice versa. Les valeurs mark, position, limit, capacity de ces deux Buffer(s) sont indépendantes l'une de l'autre.
Par exemple :
Buffer_slice_ex1.java

CharBuffer buffer1 = CharBuffer.allocate(10); // capacity = 10  

// Write data to buffer1:
buffer1.put('A');
buffer1.put('B');
buffer1.put('C');

buffer1.position(1); // Set position to 1.
buffer1.limit(7); // Set limit to 7.

CharBuffer buffer2 = buffer1.slice();

System.out.printf("buffer2, capcity: %d, limit: %d, position: %d%n%n",
              buffer2.capacity(), buffer2.limit(), buffer2.position());

// Change data in buffer2:
buffer2.put('D');
buffer2.put('E');
buffer2.put('F');

//
buffer1.position(0);
buffer1.limit(4);
// Read data in buffer1:
while(buffer1.hasRemaining()) {
    System.out.println(buffer1.get());
}
Output:

buffer2, capcity: 6, limit: 6, position: 0

A
D
E
F

16- duplicate()


public abstract Buffer duplicate();
Renvoyer un nouveau Buffer qui est un cliché de ce Buffer.
Les données du nouveau Buffer seront celles de ce Buffer. Les modifications apportées aux données de ce Buffer seront visibles dans le nouveau Buffer, et vice versa; les valeurs de position, de limit et de mark des deux Buffer seront indépendantes. Lorsqu'ils sont nouvellement créés, deux Buffer(s) disposent de mêmes valeurs position, limit, mark.
Par exemple :
Buffer_duplicate_ex1.java

CharBuffer buffer1 = CharBuffer.allocate(10); // capacity = 10  

// Write data to buffer1:
buffer1.put('A');
buffer1.put('B');
buffer1.put('C');

buffer1.position(1); // Set position to 1.
buffer1.limit(7); // Set limit to 7.

CharBuffer buffer2 = buffer1.duplicate();

System.out.printf("buffer2, capcity: %d, limit: %d, position: %d%n%n",
              buffer2.capacity(), buffer2.limit(), buffer2.position());

// Change data in buffer2:
buffer2.put('D');
buffer2.put('E');
buffer2.put('F');

//
buffer1.position(0);
buffer1.limit(4);
// Read data in buffer1:
while(buffer1.hasRemaining()) {
    System.out.println(buffer1.get());
}
Output:

buffer2, capcity: 10, limit: 7, position: 1

A
D
E
F

17- array()


public abstract Object array(); // Optional Operation.
Renvoyer un tableau contenant les éléments de ce Buffer si effectivement ce Buffer utilise des tableaux comme technique pour stocker les éléments. Il s'agit d'une opération facultative, qui peut ne pas être prise en charge dans la sous-classe de Buffer. Si cette méthode n'est pas prise en charge, elle lancera une UnsupportedOperationException. Vérifier si ce Buffer prend en charge les tableaux à l'aide de la méthode hasArray().
La plupart des sous-classes Buffer disponibles dans le JDK utilisent un tableau interne pour stocker les éléments.
Class Has Array?
ByteBuffer true
MappedByteBuffer true
ShortBuffer true
IntBuffer true
FloatBuffer true
LongBuffer true
DoubleBuffer true
CharBuffer true
Par exemple :
Buffer_array_ex1.java

CharBuffer charBuffer = CharBuffer.allocate(5); // capacity = 5

// Write data to charBuffer:
charBuffer.put('A');
charBuffer.put('B');
charBuffer.put('C');

boolean hasArray = charBuffer.hasArray(); // true

if(hasArray)  {
    char[] charArray = charBuffer.array();
    System.out.println("charArray.length: " + charArray.length);  // 5
    for(char ch: charArray)  {
        System.out.println(ch + " --> " + (int)ch);    // char and code
    }
}
Output:

charArray.length: 5
A --> 65
B --> 66
C --> 67
--> 0
--> 0

18- hasArray()


public abstract boolean hasArray();
Renvoyer true si ce Buffer utilise des tableaux comme technique pour stocker des éléments, sinon renvoie false. Il s'agit d'une opération facultative, qui peut ne pas être prise en charge dans la sous-classe de Buffer.
La plupart des sous-classes Buffer disponibles dans le JDK utilisent un tableau interne pour stocker les éléments.
Class Has Array?
ByteBuffer true
MappedByteBuffer true
ShortBuffer true
IntBuffer true
FloatBuffer true
LongBuffer true
DoubleBuffer true
CharBuffer true

19- arrayOffset()


public abstract int arrayOffset();

20- isReadOnly()


public abstract boolean isReadOnly();
Vérifier si ce Buffer est en lecture seule (read-only) ou non. Il s'agit d'une opération facultative, qui peut ne pas être prise en charge dans la sous-classe de Buffer et une UnsupportedOperationException sera levée.
La plupart des sous-classes Buffer disponibles dans le JDK prennent en charge les modes de lecture et d'écriture (par défaut) :
Class Read-Only
by default?
Support
Read-Only?
ByteBuffer false true
MappedByteBuffer false true
ShortBuffer false true
IntBuffer false true
FloatBuffer false true
LongBuffer false true
DoubleBuffer false true
CharBuffer false true
Par exemple :
Buffer_isReadOnly_ex1.java

Buffer b1 = ByteBuffer.allocate(10);
Buffer b2 = MappedByteBuffer.allocate(10);
Buffer b3 = ShortBuffer.allocate(10);
Buffer b4 = IntBuffer.allocate(10);
Buffer b5 = FloatBuffer.allocate(10);
Buffer b6 = LongBuffer.allocate(10);
Buffer b7 = DoubleBuffer.allocate(10);
Buffer b8 = CharBuffer.allocate(10);

Buffer[] buffers = new Buffer[] { b1, b2, b3, b4, b5, b6, b7, b8 };

for (Buffer buffer : buffers) {
    System.out.println(buffer.getClass().getSimpleName() + " --> " + buffer.isReadOnly());
}
Output:

HeapByteBuffer --> false
HeapByteBuffer --> false
HeapShortBuffer --> false
HeapIntBuffer --> false
HeapFloatBuffer --> false
HeapLongBuffer --> false
HeapDoubleBuffer --> false
HeapCharBuffer --> false
Par exemple : Créer un CharBuffer lecture seule:
Buffer_isReadOnly_ex2.java

CharBuffer charBuffer = CharBuffer.allocate(10); // capacity = 10
// Write data to charBuffer.
charBuffer.put('A');
charBuffer.put('B');
charBuffer.put('C');

// Create a read-only CharBuffer.
CharBuffer readOnlyBuffer = charBuffer.asReadOnlyBuffer();

System.out.println("Write data to read-only buffer:");
readOnlyBuffer.put('D'); // ==> java.nio.ReadOnlyBufferException
Output:

Write data to read-only buffer:
Exception in thread "main" java.nio.ReadOnlyBufferException
    at java.base/java.nio.HeapCharBufferR.put(HeapCharBufferR.java:202)
    at org.o7planning.buffer.ex.Buffer_isReadOnly_ex2.main(Buffer_isReadOnly_ex2.java:18)
Par exemple : Créer les autres Buffer(s) lecture seule : ByteBuffer, MappedByteBuffer, ShortBuffer, ...
Buffer_isReadOnly_ex3.java

package org.o7planning.buffer.ex;

import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.MappedByteBuffer;
import java.nio.ShortBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class Buffer_isReadOnly_ex3 {

    public static void main(String[] args) throws IOException {
        ByteBuffer b1 = ByteBuffer.allocate(10);
        
        //
        Path pathToWrite = Paths.get("/Volumes/Data/test/out-file.txt");
        FileChannel fileChannel = (FileChannel) Files.newByteChannel(pathToWrite, //
                                                StandardOpenOption.READ,
                                                StandardOpenOption.WRITE,
                                                StandardOpenOption.TRUNCATE_EXISTING);
        
        CharBuffer charBuffer = CharBuffer.wrap("This will be written to the file");
        MappedByteBuffer b2 = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, charBuffer.length());
        //
        ShortBuffer b3 = ShortBuffer.allocate(10);
        IntBuffer b4 = IntBuffer.allocate(10);
        FloatBuffer b5 = FloatBuffer.allocate(10);
        LongBuffer b6 = LongBuffer.allocate(10);
        DoubleBuffer b7 = DoubleBuffer.allocate(10);
        CharBuffer b8 = CharBuffer.allocate(10);
        
        Buffer[] buffers = new Buffer[] { b1, b2, b3, b4, b5, b6, b7, b8 };
        for (Buffer buffer : buffers) {
            System.out.println(buffer.getClass().getSimpleName() + " --> " + buffer.isReadOnly());
        }
        System.out.println(" --------- ");
        
        ByteBuffer b1r = b1.asReadOnlyBuffer();
        MappedByteBuffer b2r = (MappedByteBuffer) b2.asReadOnlyBuffer();
        ShortBuffer b3r = b3.asReadOnlyBuffer();
        IntBuffer b4r = b4.asReadOnlyBuffer();
        FloatBuffer b5r = b5.asReadOnlyBuffer();
        LongBuffer b6r = b6.asReadOnlyBuffer();
        DoubleBuffer b7r = b7.asReadOnlyBuffer();
        CharBuffer b8r = b8.asReadOnlyBuffer();
        
        Buffer[] readOnlyBuffers = new Buffer[] { b1r, b2r, b3r, b4r, b5r, b6r, b7r, b8r };
        
        for (Buffer buffer : readOnlyBuffers) {
            System.out.println(buffer.getClass().getSimpleName() + " --> " + buffer.isReadOnly());
        }
    }
}
Output:

HeapByteBuffer --> false
DirectByteBuffer --> false
HeapShortBuffer --> false
HeapIntBuffer --> false
HeapFloatBuffer --> false
HeapLongBuffer --> false
HeapDoubleBuffer --> false
HeapCharBuffer --> false
 ---------
HeapByteBufferR --> true
DirectByteBufferR --> true
HeapShortBufferR --> true
HeapIntBufferR --> true
HeapFloatBufferR --> true
HeapLongBufferR --> true
HeapDoubleBufferR --> true
HeapCharBufferR --> true

21- isDirect()


public abstract boolean isDirect();

View more Tutorials:

Peut-être que vous êtes intéressé

Voici des leçons en ligne à part du site web o7planning que nous recommandons. La liste comprend des leçons en ligne et celles en promo.