devstory

Le Tutoriel de Java ReadableByteChannel

  1. ReadableByteChannel
  2. Methods
  3. read(ByteBuffer)
  4. Example 1
  5. Example 2

1. ReadableByteChannel

Si vous êtes débutant avec Java NIO, il est utile de lire tout d'abord les articles suivants pour acquérir des connaissances de bases :
  • Java Nio
ReadableByteChannel est une interface qui s'étend à partir de l'interface Channel, qui représente les canaux pouvant lire les bytes d'un périphérique d'IO.
public interface ReadableByteChannel extends Channel
ReadableByteChannel ne fournit qu'une seule méthode, laquelle est utilisée pour lire des bytes dans un ByteBuffer. Vous pouvez convoquer cette méthode à plusieurs reprises pour lire toutes les données à partir du Channel.
public int read(ByteBuffer dst) throws IOException;
Une seule opération de lecture sur le Channel peut avoir lieu à la fois. Cela signifie que si un thread lance une opération de lecture sur un Channel, les autres threads ne peuvent pas lire sur ce Channel, ils sont bloqués jusqu'à ce que l'opération soit terminée. D'autres opérations d'IO peuvent être effectuées en même temps que l'opération de lecture en fonction du type de Channel.
La hiérarchie des interfaces et des classes liées à ReadableByteChannel:

2. Methods

ReadableByteChannel ne fournit qu'une seule méthode de plus par rapport à son interface parent.
public int read(ByteBuffer dst) throws IOException;
D'autres méthodes héritées de l'interface Channel:
public boolean isOpen();  
public void close() throws IOException;

3. read(ByteBuffer)

public int read(ByteBuffer byteBuffer) throws IOException;
La méthode read(ByteBuffer) permet de lire une séquence de bytes à partir de ce ReadableByteChannel et affecte les éléments entre position et limit-1 sur le ByteBuffer. Il lira autant que possible et renverra le nombre de bytes lus. Renvoie -1 si la fin du canal est atteinte.
  • Chaque byte affecté au ByteBuffer augmentera la position du curseur de 1.
  • Avant de convoquer cette méthode, vous devez convoquer la méthode ByteBuffer.clear() pour définir position = 0 et limit = capacity.
  • Le nombre maximal de bytes pouvant être lus dans un appel de cette méthode est byteBuffer.limit()-byteBuffer.position().
Une seule opération de lecture sur le Channel peut avoir lieu à la fois. Cela signifie que si un thread lance une opération de lecture sur un Channel, les autres threads ne peuvent pas lire sur ce Channel, ils sont bloqués jusqu'à ce que l'opération soit terminée. D'autres opérations d'IO peuvent être effectuées en même temps que l'opération de lecture en fonction du type de Channel.

4. Example 1

Exemple : Utiliser ReadableByteChannel pour lire les données d'un InputStream, en particulier d'un ByteArrayInputStream.
Ci-dessous, une image des bytes de la chaîne "JP日本-八洲" au format UTF-8 (UTF-8 utilise 1, 2, 3 ou 4 bytes pour stocker un caractère).
ReadableByteChannel_ex1.java
package org.o7planning.readablebytechannel.ex;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class ReadableByteChannel_ex1 {

    public static void main(String[] args) throws IOException {
        InputStream inputStream = null;
        ReadableByteChannel channel = null;
        try {
            byte[] byteData = "JP日本-八洲".getBytes("UTF-8");
            inputStream = new ByteArrayInputStream(byteData);
            
            // Create ReadableByteChannel to read a InputStream.
            channel = Channels.newChannel(inputStream);
            ByteBuffer buffer = ByteBuffer.allocate(10);

            int bytesRead = -1;
            while ((bytesRead = channel.read(buffer)) > -1) {
                System.out.println(" --- bytesRead : " + bytesRead + " ---- ");
                // Set limit = current position; position = 0;
                buffer.flip();

                while (buffer.hasRemaining()) {
                    byte b = buffer.get(); // [-128,127]
                    int charCode = Byte.toUnsignedInt(b); // [0,255] Java 8+
                    System.out.println((char) charCode + " --> " + charCode);
                }
                // Set position = 0; limit = capacity.
                buffer.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeQuietly(inputStream);
            closeQuietly(channel);
        }
    }

    private static void closeQuietly(Closeable closeable) {
        try {
            closeable.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Output:
--- bytesRead : 10 ----
J --> 74
P --> 80
æ --> 230
— --> 151
¥ --> 165
æ --> 230
œ --> 156
¬ --> 172
- --> 45
å --> 229
 --- bytesRead : 5 ----
… --> 133
« --> 171
æ --> 230
´ --> 180
² --> 178
InputStream et Channel implémentent ou étendent tous les deux à partir de l'interface Closeable, il a donc la possibilité de se fermer automatiquement si vous utilisez la syntaxe "Closeable-try-catch". Et on réécrira l'exemple ci-dessus de manière plus succincte.
ReadableByteChannel_ex1b.java
package org.o7planning.readablebytechannel.ex;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class ReadableByteChannel_ex1b {

    public static void main(String[] args) throws IOException {
        byte[] byteData = "JP日本-八洲".getBytes("UTF-8");

        // Closeable-try-catch Syntax:
        try (InputStream inputStream = new ByteArrayInputStream(byteData);
                // Create ReadableByteChannel to read a InputStream.
                ReadableByteChannel channel = Channels.newChannel(inputStream);) { // try
            ByteBuffer buffer = ByteBuffer.allocate(10);

            int bytesRead = -1;
            while ((bytesRead = channel.read(buffer)) > -1) {
                System.out.println(" --- bytesRead : " + bytesRead + " ---- ");
                // Set limit = current position; position = 0;
                buffer.flip();

                while (buffer.hasRemaining()) {
                    byte b = buffer.get(); // [-128,127]
                    int charCode = Byte.toUnsignedInt(b); // [0,255] Java 8+
                    System.out.println((char) charCode + " --> " + charCode);
                }
                // Set position = 0; limit = capacity.
                buffer.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. Example 2

Exemple : Lire un fichier de données sur le réseau.
ReadableByteChannel_ex2.java
String urlString = "https://s3.o7planning.com/txt/utf8-file-without-bom.txt";
URL url = new URL(urlString);

try (InputStream inputStream = url.openStream();
        // Create ReadableByteChannel to read a InputStream.
        ReadableByteChannel channel = Channels.newChannel(inputStream);) { // try
    
    ByteBuffer buffer = ByteBuffer.allocate(10);
    int bytesRead = -1;
    while ((bytesRead = channel.read(buffer)) > -1) {
        System.out.println(" --- bytesRead : " + bytesRead + " ---- ");
        // Set limit = current position; position = 0;
        buffer.flip();

        while (buffer.hasRemaining()) {
            byte b = buffer.get(); // [-128,127]
            int charCode = Byte.toUnsignedInt(b); // [0,255] Java 8+
            System.out.println((char) charCode + " --> " + charCode);
        }
        // Set position = 0; limit = capacity.
        buffer.clear();
    }
} catch (Exception e) {
    e.printStackTrace();
}
Output:
--- bytesRead : 10 ----
J --> 74
P --> 80
æ --> 230
— --> 151
¥ --> 165
æ --> 230
œ --> 156
¬ --> 172
- --> 45
å --> 229
 --- bytesRead : 5 ----
… --> 133
« --> 171
æ --> 230
´ --> 180
² --> 178