Una breve introducción a JavaINO (1)

Javaino

  • Esto es Java New IOtambién llamada sin bloqueo IONone Blocking IO
  • Es un producto nuevo y JDK 1.4luego provistoIO API

2. Función

  • Proporciona un método de trabajo IOdiferente al estándar.IO
  • Alternativa a la norma Java IOdeIO API

3. Nuevas características

En contraste Java IO, NIOlas nuevas características son las siguientes

Inserte la descripción de la imagen aquí

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 NIOLos 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

  1. 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) )
  2. 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.
  3. 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.
  4. 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.
101 artículos originales publicados · Me gustaron 47 · Visitantes más de 10,000

Supongo que te gusta

Origin blog.csdn.net/TONGZONGE/article/details/104453138
Recomendado
Clasificación