Javaino
- Cela est
Java New IO
aussi appelé non-blocage IONone Blocking IO
- Est-ce un tout nouveau et
JDK 1.4
plus tard fourniIO API
2. Fonction
- Fournit une méthode de travail
IO
différente de la normeIO
- Alternative à la norme
Java IO
deIO API
3. Nouvelles fonctionnalités
En revanche Java IO
, NIO
les nouvelles fonctionnalités sont les suivantes
La principale différence entre Java NIO et IO
Style IO | Style NIO |
---|---|
Orienté octets | Orienté cache |
Blocage des E / S | Non bloquant (IO non bloquant) |
(Aucun) | Sélecteurs |
4. Composants principaux
Java NIO
Les principaux composants comprennent:
- Canal (
Channel
) - Tampon (
Buffer
) - Sélecteur (
Selectors
)
5. Allocation et accès à NIO_Buffer_
- Trois paramètres importants dans le cache
/**
* 测试缓存分配
*/
@Test
public void test1(){
// capacity 分配缓存大小
int capacity = 1024;
ByteBuffer buffer = ByteBuffer.allocate(capacity);
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
// 向缓存中存数据 put();
buffer.put("hello world!".getBytes());
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
//flip() 方法切换到读的状态
buffer.flip();
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
// 从缓存中取数据 get()
//byte b = buffer.get();
byte[] dst = new byte[buffer.limit()];
buffer.get(dst);
System.out.println(new String(dst));
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
// rewind() 重写 其起始位置从零开始
buffer.rewind();
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
//clear() 清空缓存 限制增大 limit = capacity
buffer.clear();
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println((char) buffer.get());
System.out.println("--------------------------------------------------------");
}
6. Marquer le paramètre et les autres méthodes du cache NIO_Buffer_
/**
* 测试标记
*/
@Test
public void test2() {
// capacity 分配缓存大小
int capacity = 1024;
ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);
byteBuffer.put("Hello world!".getBytes());
//flip() 方法切换到读的状态
byteBuffer.flip();
byte[] b = new byte[2];
byteBuffer.get(b);
System.out.println(new String(b));
System.out.println("--------------------------------------------------------");
System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
System.out.println("limit(限制):" + byteBuffer.limit());
System.out.println("position(起始位置):" + byteBuffer.position());
// mark()做标记
byteBuffer.mark();
byteBuffer.get(b);
System.out.println(new String(b));
System.out.println("--------------------------------------------------------");
System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
System.out.println("limit(限制):" + byteBuffer.limit());
System.out.println("position(起始位置):" + byteBuffer.position());
// reset()回到mark标记的位置 Invariants: mark <= position <= limit <= capacity
byteBuffer.reset();
System.out.println("--------------------------------------------------------");
System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
System.out.println("limit(限制):" + byteBuffer.limit());
System.out.println("position(起始位置):" + byteBuffer.position());
}
7. NIO_Buffer_ cache direct et cache indirect
/**
* 直接缓存区
*/
@Test
public void test3(){
// 分配直接缓存区
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
System.out.println("capacity(缓存大小):" + buf.capacity());
System.out.println("limit(限制):" + buf.limit());
System.out.println("position(起始位置):" + buf.position());
System.out.println("是否为直接缓存区:" + buf.isDirect());
}
8. Type et méthode de copie du canal NIO_Buffer_
@Test
/**
* 利用通道channel进行文件复制
*/
public void test4(){
FileInputStream fin = null;
FileOutputStream fout = null;
FileChannel finChannel = null;
FileChannel foutChannel = null;
try {
fin = new FileInputStream("3.jpg");
fout = new FileOutputStream("4.jpg");
// 获得通道
finChannel = fin.getChannel();
foutChannel = fout.getChannel();
// 获得缓存
ByteBuffer buffer = ByteBuffer.allocate(1024);//反复读3.jpg的字节到缓存 如果=1 即为读完
while(finChannel.read(buffer)!=-1){
//position定位到开头以便从缓存中获取数据
buffer.flip();
// 将缓存数据写入通道
foutChannel.write(buffer);
//清空缓存position定位到开头以便下次读通道读字节
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 关闭通道
try {
if(finChannel!=null) finChannel.close();
if(foutChannel!=null) foutChannel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Test
/**
* JDK1.7之后获得的通道的方法
*/
public void test5(){
FileChannel fin = null;
FileChannel fout = null;
try {
fin = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.READ);
fout = FileChannel.open(Paths.get("5.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);
// 创建缓存
MappedByteBuffer finmap = fin.map(FileChannel.MapMode.READ_ONLY,0,fin.size());
MappedByteBuffer outmap = fout.map(FileChannel.MapMode.READ_WRITE,0,fin.size());
//获得3.jpg字节
byte[] dst = new byte[finmap.limit()];
finmap.get(dst);
// 把字节放入缓存
outmap.put(dst);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(fin != null) fin.close();
if(fout != null) fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* JDK1.7之后的获取通道方法
* 通道间直接缓存交换数据
* transferFrom()
* transferTo()
*/
@Test
public void test6(){
FileChannel fin = null;
FileChannel fout = null;
try {
fin = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.READ);
fout = FileChannel.open(Paths.get("6.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);
// 创建缓存
fin.transferTo(0,fin.size(),fout);
fout.transferFrom(fin,0,fin.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(fin != null) fin.close();
if(fout != null) fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
9. Dispersion et agrégation de INO_Buffer
/**
* 分散和聚集
*/
@Test
public void test7() throws Exception {
// 获得通道
FileChannel channel = new RandomAccessFile("src/edu/xalead/TestBuffer.java",
"rw").getChannel();
// 创建缓存
ByteBuffer buffer1 = ByteBuffer.allocate(1024);
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
ByteBuffer buffer3 = ByteBuffer.allocate(1024);
ByteBuffer buffer4 = ByteBuffer.allocate(1024);
ByteBuffer buffer5 = ByteBuffer.allocate(1024);
ByteBuffer buffer6 = ByteBuffer.allocate(1024);
ByteBuffer buffer7 = ByteBuffer.allocate(1024);
ByteBuffer buffer8 = ByteBuffer.allocate(1024);
ByteBuffer buffer9 = ByteBuffer.allocate(1024);
ByteBuffer buffer10 = ByteBuffer.allocate(1024);
// 分散读取
ByteBuffer[] buffers = {buffer1,buffer2,buffer3,buffer4, buffer5, buffer6, buffer7, buffer8,buffer9,buffer10};
channel.read(buffers);
for(ByteBuffer buffer: buffers){
System.out.println(new String(buffer.array(),0,buffer.limit()));
System.out.println("-----------------------------------------------------------");
}
//聚集写入
FileChannel channel1 = new RandomAccessFile("T.java","rw").getChannel();
// 把buffer的position恢复到起始位置
for(ByteBuffer buffer:buffers){
buffer.flip();
}
channel1.write(buffers);
channel.close();
channel1.close();
}
10 Résumé NIO
Tampon
Type de cache (utilisé pour mettre en cache différents types de données, en omettant la conversion de type)
- ByteBuffer
- IntBuffer
- ShortBuffer
- LongBuffer
- CharBuffer
- FloatBuffer
- DoubleBuffer
Deux méthodes principales de mise en cache et d'accès aux données
- put () enregistrer les données dans le cache
- get () récupère les données du cache
Quatre paramètres dans le cache
- capacité
- limite
- position
- marque
Tampon direct et tampon indirect:
Tampon non direct: allouer le tampon par la méthode allocate () et établir le tampon dans la mémoire de la JVM
Tampon direct: allouer le tampon direct par la méthode allocateDirect () et établir le tampon dans la mémoire physique. Peut améliorer l'efficacité
- Le tampon d'octets est direct ou indirect. S'il s'agit d'un tampon d'octets direct, la machine virtuelle Java fera de son mieux pour effectuer des opérations d'E / S natives directement sur ce tampon. C'est-à-dire qu'avant chaque (ou après) une opération d'E / S native du système d'exploitation sous-jacent est appelée, la machine virtuelle essaiera d'éviter de copier le contenu du tampon dans le tampon intermédiaire (ou de copier le contenu du tampon intermédiaire ).
- Des tampons d'octets directs peuvent être créés en appelant la méthode d'usine allocateDirect () de cette classe . Les tampons renvoyés par cette méthode coûtent généralement plus cher à allouer et désallouer que les tampons non directs. Le contenu des tampons directs peut résider en dehors du tas de récupération de place conventionnel, de sorte que leur impact sur les besoins en mémoire de l'application peut ne pas être évident. Par conséquent, il est recommandé que les tampons directs soient principalement alloués aux grands tampons persistants qui sont sensibles aux opérations d'E / S natives du système sous-jacent. En général, il est préférable d'allouer des tampons directs uniquement lorsqu'ils peuvent fournir un avantage significatif dans les performances du programme.
- Des tampons d'octets directs peuvent également être créés en mappant directement la zone de fichiers dans la mémoire via la méthode FileChannel map () . Cette méthode renvoie MappedByteBuffer . L'implémentation de la plate-forme Java facilite la création de tampons d'octets directs à partir du code natif via JNI. Si une instance de tampon dans ces tampons fait référence à une zone de mémoire inaccessible, tenter d'accéder à la zone ne changera pas le contenu du tampon et provoquera un lancer pendant l'accès ou à une date ultérieure Exceptions incertaines.
- Que le tampon d'octets soit un tampon direct ou un tampon indirect peut être déterminé en appelant sa méthode isDirect () . Cette méthode est fournie pour permettre la gestion explicite du tampon dans le code critique pour les performances.