Java NIO doit principalement comprendre les trois concepts fondamentaux de tampons, de canaux et de sélecteurs en complément des E/S Java pour améliorer l'efficacité de la transmission de données de gros volumes.
(Tutoriel recommandé : cours Java)
Il est préférable d'avoir des connaissances de base en programmation réseau avant d'apprendre NIO
Flux d'E/S Java
Programmation réseau Java
Java NIO : Buffer
Channel (Channel), comme l'un des trois concepts fondamentaux de NIO (tampon, canal, sélecteur), est utilisé dans Transmettre efficacement données entre le tampon d'octets et l'entité (fichier ou socket) de l'autre côté du canal (le noyau est de transmettre des données)
Le modèle général de la programmation NIO est le suivant : remplissez les données dans la section du mot d'envoi buffer --> Envoyer au fichier homologue du canal ou au socket via le canal
Bases du canal
Le but de l'utilisation du canal est de transmettre des données avant utilisation. être ouvert et le canal doit être fermé après utilisation
Ouvrir le canal
Nous savons qu'il existe deux grandes catégories d'E/S : File IO et Stream I /O, qui correspondent à Il existe deux types de canaux : le canal de fichier (FileChannel) et le canal de socket (SocketChannel, ServerSocketChannel, DatagramChannel)
Pour les canaux de socket, utilisez la méthode de fabrique statique pour ouvrir
SocketChannel sc = SocketChannel.open(); ServerSocketChannel sc = ServerSocketChannel.open(); DatagramChannel sc = DatagramChannel.open();
Pour les canaux de fichiers Il ne peut être obtenu qu'en appelant la méthode getChannel() sur un objet RandomAccessFile, FileInputStream et FileOutputStream à ByteBuffer, puis en ouvrant le canal de fichier et en plaçant les données du tampon dans le canal de fichier.
FileInputStream in = new FileInputStream("/tmp/a.txt"); FileChannel fc = in.getChannel();
Fermez le canal
Tout comme Socket, FileInputStream et d'autres objets doivent être fermés après utilisation, le canal doit également être fermé après utilisation. Un canal ouvert représente une connexion spécifique à un service d'E/S spécifique et encapsule l'état de cette connexion. Lorsque le canal est fermé, la connexion est perdue et rien n'y est connecté.
Mode bloquant et non bloquant
Le canal dispose de deux modes de fonctionnement : bloquant et non bloquant. Le canal en mode non bloquant ne se mettra jamais en veille, et le. L'opération demandée sera terminée immédiatement, ou renverra un résultat indiquant qu'aucune opération n'a été effectuée (voir la description du canal Socket pour plus de détails). Seuls les canaux orientés flux peuvent utiliser le mode non bloquant
Canaux de fichiers
Les canaux de fichiers sont utilisés pour accéder aux fichiers en appelant getChannel sur un objet RandomAccessFile, FileInputStream, FileOutputStream ( ) méthode pour obtenir. L'appel de la méthode getChannel renvoie un objet FileChannel connecté au même fichier avec les mêmes droits d'accès que l'objet fichier.
Accès aux fichiers
Le but de l'utilisation des canaux de fichiers est de lire et d'écrire des fichiers. L'API de lecture et d'écriture du canal est la suivante :
//准备数据并放入字节缓冲区 ByteBuffer bf = ByteBuffer.allocate(1024); bf.put("i am cool".getBytes()); bf.flip(); //打开文件通道 FileOutputStream out = new FileOutputStream("/tmp/a.txt"); FileChannel fc = out.getChannel(); //数据传输 fc.write(bf); //关闭通道 fc.close();
public abstract int read(ByteBuffer dst) throws IOException; public abstract int write(ByteBuffer src) throws IOException;
Position et fichier du canal de fichier. trou
Position du canal de fichier (position) C'est la position d'un fichier ordinaire. La valeur de position détermine quelle position dans le fichier sera lue ou écrite ensuite Lecture des données au-delà. la fin du fichier renverra -1 (fichier EOF)L'écriture de données à une position au-delà de la fin du fichier provoquera des trous dans le fichier : par exemple, un fichier contient actuellement 10 octets, mais l'écriture de données à la position =20 à ce moment fera que la position entre 10 et 20 sera vide. Données, c'est un trou de fichier
opération forcée
L'opération forcée force le canal. pour appliquer immédiatement toutes les modifications au fichier disque (pour éviter que les modifications ne soient perdues en raison d'un temps d'arrêt du système)//打开文件channel RandomAccessFile f = new RandomAccessFile("/tmp/a.txt", "r"); FileChannel fc = f.getChannel(); //从channel中读取数据,直到文件尾 ByteBuffer bb = ByteBuffer.allocate(1024); while (fc.read(bb) != -1) { ; } //翻转(读之前需要先进行翻转) bb.flip(); StringBuilder builder = new StringBuilder(); //把每一个字节转为字符(ascii编码) while (bb.hasRemaining()) { builder.append((char) bb.get()); } System.out.println(builder.toString());
Mappage de fichiers mémoire
FileChannel fournit une méthode map() , qui peut établir une connexion virtuelle entre un fichier ouvert et un type spécial de carte mémoire ByteBuffer (MappedByteBuffer). Étant donné que l'objet MappedByteBuffer renvoyé par la méthode map est un tampon direct, il est très efficace d'exploiter des fichiers via MappedByteBuffer (en particulier lors du transfert de grandes quantités de données)Utilisation de MappedByteBuffer
Lire des fichiers via MappedByteBufferpublic abstract void force(boolean metaData) throws IOException;
Trois modes de MappedByteBuffer
READ_ONLYREAD_WRITEPRIVÉ
Les modes lecture seule et lecture-écriture sont faciles à comprendre. En mode PRIVÉ, l'opération d'écriture écrit un tampon temporaire et n'écrit pas réellement le fichier. (Copier en écrivant l'idée)Canal Socket
Le canal Socket peut fonctionner en mode non bloquant et est facultatif. Ces deux points nous font ne plus penser à la programmation réseau. . Vous devez créer un thread pour chaque connexion Socket, mais utilisez un seul thread pour gérer des centaines ou des milliers de connexions Socket. Tous les canaux Socket créeront un objet Socket d'un objet lorsqu'ils sont instanciés. Les canaux Socket ne sont pas responsables des opérations liées au protocole sont déléguées aux objets socket homologues (tels que les objets SocketChannel sont délégués à Socket. objet)非阻塞模式
相较于传统Java Socket的阻塞模式,SocketChannel提供了非阻塞模式,以构建高性能的网络应用程序
非阻塞模式下,几乎所有的操作都是立刻返回的。比如下面的SocketChannel运行在非阻塞模式下,connect操作会立即返回,如果success为true代表连接已经建立成功了, 如果success为false, 代表连接还在建立中(tcp连接需要一些时间)。
//打开Socket通道 SocketChannel ch = SocketChannel.open(); //非阻塞模式 ch.configureBlocking(false); //连接服务器 boolean success = ch.connect(InetSocketAddress.createUnresolved("127.0.0.1", 7001)); //轮训连接状态, 如果连接还未建立就可以做一些别的工作 while (!ch.finishConnect()){ //dosomething else } //连接建立, 做正事 //do something;
ServerSocketChannel
ServerSocketChannel与ServerSocket类似,只是可以运行在非阻塞模式下
下为一个通过ServerSocketChannel构建服务器的简单例子,主要体现了非阻塞模式,核心思想与ServerSocket类似
ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); ssc.bind(new InetSocketAddress(7001)); while (true){ SocketChannel sc = ssc.accept(); if(sc != null){ handle(sc); }else { Thread.sleep(1000); } }
SocketChannel 与 DatagramChannel
SocketChannel 对应 Socket, 模拟TCP协议;DatagramChannel对应DatagramSocket, 模拟UDP协议
二者的使用与SeverSocketChannel大同小异,看API即可
工具类
文体通道那里我们提到过, 通过只能操作字节缓冲区, 编解码需要应用程序自己实现。如果我们想在通道上直接操作字符,我们就需要使用工具类Channels,工具类Channels提供了通道与流互相转换、通道转换为阅读器书写器的能力,具体API入下
//通道 --> 输入输出流 public static OutputStream newOutputStream(final WritableByteChannel ch); public static InputStream newInputStream(final AsynchronousByteChannel ch); //输入输出流 --> 通道 public static ReadableByteChannel newChannel(final InputStream in); public static WritableByteChannel newChannel(final OutputStream out); //通道 --> 阅读器书写器 public static Reader newReader(ReadableByteChannel ch, String csName); public static Writer newWriter(WritableByteChannel ch, String csName);
通过将通道转换为阅读器、书写器我们就可以直接在通道上操作字符。
RandomAccessFile f = new RandomAccessFile("/tmp/a.txt", "r"); FileChannel fc = f.getChannel(); //通道转换为阅读器,UTF-8编码 Reader reader = Channels.newReader(fc, "UTF-8"); int i = 0, s = 0; char[] buff = new char[1024]; while ((i = reader.read(buff, s, 1024 - s)) != -1) { s += i; } for (i = 0; i < s; i++) { System.out.print(buff[i]); }
总结
通道主要分为文件通道和套接字通道。
对于文件操作:如果是大文件使用通道的文件内存映射特性(MappedByteBuffer)来有利于提升传输性能, 否则我更倾向传统的I/O流模式(字符API);对于套接字操作, 使用通道可以运行在非阻塞模式并且是可选择的,利于构建高性能网络应用程序。
相关推荐:java入门
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!