Maison > Java > javaDidacticiel > Comment utiliser les fonctions NIO pour des opérations d'E/S efficaces en Java

Comment utiliser les fonctions NIO pour des opérations d'E/S efficaces en Java

WBOY
Libérer: 2023-06-26 17:06:10
original
1106 Les gens l'ont consulté

Avec le développement rapide de la technologie Internet, la demande de divers systèmes d'applications à grande échelle continue d'augmenter et le besoin d'opérations d'E/S efficaces devient de plus en plus urgent. En tant que langage de programmation couramment utilisé, Java est de plus en plus utilisé dans les opérations d'E/S. La fonction NIO, en tant que méthode de mise en œuvre d'opérations d'E/S efficaces, a également attiré beaucoup d'attention ces dernières années. Cet article explique comment utiliser les fonctions NIO en Java pour effectuer des opérations d'E/S efficaces.

1. Introduction à NIO

NIO, ou New I/O, est une nouvelle API IO introduite dans la version Java 1.4. Par rapport à l'API IO traditionnelle, NIO implémente des opérations IO non bloquantes. L'API IO traditionnelle est orientée flux, tandis que NIO est orienté bloc. L'inconvénient du streaming IO est que lorsqu'un fichier volumineux doit être lu et écrit, de nombreux problèmes de blocage de lecture et d'écriture IO se produiront, affectant sérieusement l'efficacité du programme. Le bloc IO peut éviter le blocage inutile des IO et améliorer l'efficacité du fonctionnement des IO lors de la lecture et de l'écriture d'un bloc de données. Dans le même temps, NIO fournit également un mécanisme de multiplexage efficace (Multiplexage), qui peut surveiller plusieurs événements IO en même temps et améliorer l'efficacité de la communication réseau.

2. Utilisation de NIO

  1. Classe Buffer dans NIO

La classe Buffer dans NIO est l'une des classes principales et sa fonction est de mettre en cache les données de lecture et d'écriture. Différent de l'API IO traditionnelle, Buffer dans NIO a certaines règles pour lire et écrire des données. Par exemple, avant d'écrire des données, vous devez appeler la méthode Buffer.flip() pour réinitialiser le pointeur d'écriture du tampon pour les opérations de lecture. La classe Buffer possède de nombreuses autres méthodes, telles que position(), limit(), capacité(), etc., qui peuvent être utilisées selon les besoins. De plus, il existe une variété de classes Buffer dans NIO, telles que ByteBuffer, CharBuffer, IntBuffer, etc., utilisées pour mettre en cache différents types de données.

  1. Classe Channel dans NIO

En plus de la classe Buffer, la classe Channel est également l'une des classes principales de NIO. Sa fonction est de lire et d'écrire des données. La classe Channel dans NIO comprend différents types de canaux, tels que FileChannel, DatagramChannel, etc. Contrairement à l'API IO traditionnelle, la classe Channel dans NIO peut effectuer des opérations IO non bloquantes.

  1. Classe Selector dans NIO

La classe Selector dans NIO est la classe clé pour implémenter le multiplexage dans NIO. La classe Selector peut surveiller plusieurs canaux Lorsqu'un ou plusieurs canaux ont des données qui peuvent être lues ou écrites, le sélecteur demandera au canal correspondant d'effectuer des opérations de lecture et d'écriture. L'utilisation de la classe Selector peut éviter de créer plusieurs threads pour lire et écrire plusieurs canaux, améliorant ainsi l'efficacité du programme.

3. Exemple NIO

Ce qui suit utilise un exemple pour illustrer l'utilisation de NIO. Supposons qu'il existe un fichier et que les données qu'il contient doivent être lues ligne par ligne et sorties sur la console.

  1. Lire le contenu du fichier

FileChannel peut lire le contenu du fichier via la méthode suivante :

public static void readFile(String fileName) throws IOException{
        FileInputStream fis = new FileInputStream(fileName);
        FileChannel fc = fis.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while(fc.read(buffer) != -1){
            buffer.flip();
            while(buffer.hasRemaining()){
                System.out.print((char)buffer.get());
            }
            buffer.clear();
        }

        fc.close();
        fis.close();
    }
Copier après la connexion

Dans le code, obtenez d'abord le canal de fichier FileChannel via FileInputStream, puis créez un tampon ByteBuffer et spécifiez que la taille du tampon est de 1024 octets. Lors de la lecture d'un fichier, lisez-le via la méthode fc.read(buffer) et déterminez si la lecture est terminée. Si la lecture n'est pas terminée, appelez la méthode buffer.flip() pour réinitialiser la position et la limite du tampon. Après que chaque boucle ait lu les données dans le tampon, vous devez définir la position du tampon sur 0 et la limite de la capacité du tampon, afin que le tampon puisse être réutilisé.

  1. Implémenter la lecture ligne par ligne

Vous pouvez utiliser la classe LineIterator pour implémenter la lecture ligne par ligne :

public static void readLine(String fileName) throws IOException{
        FileInputStream fis = new FileInputStream(fileName);
        FileChannel fc = fis.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        Charset charset = Charset.forName("UTF-8");
        LineIterator iterator = new LineIterator(charset.newDecoder());

        while(fc.read(buffer) != -1){
            buffer.flip();
            iterator.read(buffer, new LineHandler() {
                @Override
                public boolean handle(String line) throws Exception {
                    System.out.println(line);
                    return true;
                }

                @Override
                public void endOfFile() throws Exception {
                    System.out.println("End of File.");
                }
            });
            buffer.compact();
        }

        iterator.finish();

        fc.close();
        fis.close();
    }
Copier après la connexion

Dans le code, créez d'abord un objet LineIterator et spécifiez l'encodage du jeu de caractères en UTF-8 . Lors de la lecture du contenu du fichier, lisez le contenu du fichier ligne par ligne via la méthode iterator.read(buffer,LineHandler). La méthode handle(String line) de l'interface LineHandler est utilisée pour traiter une ligne de données lues, et la méthode endOfFile() est utilisée pour traiter la situation à la fin de la lecture du fichier. Dans la méthode handle, vous pouvez traiter une ligne de données que vous lisez, par exemple en la transmettant à la console.

  1. Utilisez la classe Selector

Vous pouvez utiliser la classe Selector pour implémenter des opérations de multiplexage :

public static void selectorSocket() throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 9999));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            int readyChannels = selector.select();
            if (readyChannels == 0) continue;

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = serverChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    socketChannel.read(buffer);
                    buffer.flip();
                    while (buffer.hasRemaining()) {
                        System.out.print((char) buffer.get());
                    }
                    buffer.clear();
                }
                keyIterator.remove();
            }
        }
    }
Copier après la connexion

Dans le code, créez d'abord un sélecteur et enregistrez un canal ServerSocketChannel pour l'écoute sur la connexion au port 9999. Dans la boucle while, surveillez les événements IO via la méthode select() du sélecteur. Lorsqu'un ou plusieurs événements IO enregistrés par le canal sont déclenchés, le sélecteur renvoie la clé de sélection correspondante. Vous pouvez utiliser la méthode SelectionKey.isAcceptable() pour déterminer le type de SelectionKey et effectuer des opérations, telles que l'enregistrement de l'opération OP_READ d'un SocketChannel.

4. Résumé

Cet article explique comment utiliser les fonctions NIO en Java pour effectuer des opérations d'E/S efficaces. En introduisant le mécanisme NIO, le problème de blocage des IO traditionnelles peut être évité et l'efficacité du programme peut être améliorée. Les classes de base de NIO incluent Buffer, Channel, Selector, etc., grâce auxquelles diverses opérations d'E/S efficaces peuvent être effectuées. Dans les applications réelles, la forme et la méthode d'utilisation des fonctions NIO doivent être déterminées en fonction des besoins et des scénarios commerciaux spécifiques pour obtenir les meilleurs résultats.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal