Javaino
- Esto es
Java New IO
también llamada sin bloqueo IONone Blocking IO
- Es un producto nuevo y
JDK 1.4
luego provistoIO API
2. Función
- Proporciona un método de trabajo
IO
diferente al estándar.IO
- Alternativa a la norma
Java IO
deIO API
3. Nuevas características
En contraste Java IO
, NIO
las nuevas características son las siguientes
La principal diferencia entre Java NIO y IO
Estilo IO | Estilo NIO |
---|---|
Orientado a bytes | Orientado a caché |
Bloqueo de IO | Sin bloqueo (IO sin bloqueo) |
(Ninguno) | Selectores |
4. Componentes principales
Java NIO
Los componentes principales incluyen:
- Canal (
Channel
) - Buffer (
Buffer
) - Selector (
Selectors
)
5. NIO_Buffer_ asignación y acceso
- Tres parámetros importantes en el caché
/**
* 测试缓存分配
*/
@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. Marcar parámetros y otros métodos de caché 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_ caché directo y caché indirecto
/**
* 直接缓存区
*/
@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. Tipo y método de copia del 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. Dispersión y agregación 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 resumen de NIO
Tampón
Tipo de caché (utilizado para almacenar en caché diferentes tipos de datos, omitiendo la conversión de tipos)
- ByteBuffer
- IntBuffer
- ShortBuffer
- LongBuffer
- CharBuffer
- FloatBuffer
- DoubleBuffer
Dos métodos principales de almacenamiento en caché y acceso a datos
- put () guardar datos en caché
- get () obtiene datos del caché
Cuatro parámetros en el caché
- capacidad
- límite
- posición
- marca
Tampón directo y tampón indirecto:
Memoria intermedia no directa: asigne la memoria intermedia mediante el método allocate () y establezca la memoria intermedia en la memoria de la JVM. Memoria
intermedia directa: asigne la memoria intermedia directa mediante el método allocateDirect () y establezca la memoria intermedia en la memoria física. Puede mejorar la eficiencia
- El búfer de bytes es directo o indirecto. Si se trata de un búfer de bytes directos, la máquina virtual Java hará todo lo posible para realizar operaciones de E / S nativas directamente en este búfer. Es decir, antes de cada (o después) de una operación de E / S nativa del sistema operativo subyacente, la máquina virtual intentará evitar copiar el contenido del búfer en el búfer intermedio (o copiar el contenido del búfer intermedio) )
- Los buffers de bytes directos se pueden crear llamando al método de fábrica allocateDirect () de esta clase . Los buffers devueltos por este método generalmente cuestan más para asignar y desasignar que los buffers no directos. El contenido de los buffers directos puede residir fuera del montón de recolección de basura convencional, por lo que su impacto en los requisitos de memoria de la aplicación puede no ser obvio. Por lo tanto, se recomienda que los buffers directos se asignen principalmente a buffers grandes y persistentes que sean susceptibles a las operaciones de E / S nativas del sistema subyacente. En general, es mejor asignar buffers directos solo cuando pueden proporcionar un beneficio significativo en el rendimiento del programa.
- Los buffers de bytes directos también se pueden crear asignando directamente el área del archivo a la memoria a través del método mapChannel map () . Este método devuelve MappedByteBuffer . La implementación de la plataforma Java facilita la creación de buffers de bytes directos a partir de código nativo a través de JNI. Si una instancia de búfer en estos búferes se refiere a un área de memoria inaccesible, intentar acceder al área no cambiará el contenido del búfer y causará un lanzamiento durante el acceso o en un momento posterior Excepciones inciertas.
- Se puede determinar si el búfer de bytes es un búfer directo o un búfer indirecto llamando a su método isDirect () . Este método se proporciona para habilitar la gestión explícita del búfer en código de rendimiento crítico.