• Java Nio


     1. 案例说明 NIO  的 Buffer

    package com.example.netty.nio;
    
    import java.nio.IntBuffer;
    
    /**
     * java.nio.BufferOverflowException
     */
    public class BasicBuffer {
        public static void main(String[] args) {
            //举例说明Buffer的使用
            //创建一个Buffer,大小为5,即可以存放5个int
            IntBuffer allocate = IntBuffer.allocate(5);
            //allocate.put(11);
            for (int i = 0; i < allocate.capacity(); i++) {
                allocate.put(i * 2);
            }
            //将buffer转换,读写切换
            allocate.flip();
    
            while (allocate.hasRemaining()) {
                System.out.println(allocate.get());
            }
        }
    }

    2. 应用实例 1-本地文件写数据(Channel:通道):

      1)   使用前面学习后的 ByteBuffer(缓冲)  和  FileChannel(通道),  将  "hello,尚硅谷"  写入到 file01.txt  中

      2)   文件不存在就创建

      3)   代码演示

    package com.example.netty.nio;
    
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class NIOFileChannel01 {
        public static void main(String[] args) throws Exception {
            String str = "Hello Word";
            //创建一个输入流 -> channel
            FileOutputStream fileOutputStream = new FileOutputStream("d://file01.txt");
    
            //通过fileOutputStream 获取对应FileChannel
            //这个fileChannel真实类型是 FileChannelImpl
            FileChannel fileChannel = fileOutputStream.getChannel();
    
            //创建一个缓冲区 ByteBuffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    
            //将str放入ByteBuffer
            byteBuffer.put(str.getBytes());
    
            //将ByteBuffer 进行 flip
            byteBuffer.flip();
    
            //将ByteBuffer 数据写入到FileChannel
            fileChannel.write(byteBuffer);
            fileOutputStream.close();
        }
    }

    3. 本地文件读数据:

      1)   使用前面学习后的 ByteBuffer(缓冲)  和  FileChannel(通道), 将  file01.txt  中的数据读入到程序,并显示在控制台屏幕

      2)   假定文件已经存在

      3)   代码演示

    package com.example.netty.nio;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class NIOFileChannel02 {
        public static void main(String[] args) throws Exception {
            File file = new File("d://file01.txt");
            //创建文件的输入流
            FileInputStream fileInputStream = new FileInputStream(file);
    
            //通过fileInputStream 获取对应的fileChannel -> 实际类型 FileChannelImpl
            FileChannel fileChannel = fileInputStream.getChannel();
    
            //创建缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate((int)file.length());
    
            //将通道的数据读入到 Buffer
            fileChannel.read(byteBuffer);
    
            //将byteBuffer的字节数据  转成String
            System.out.println(new String(byteBuffer.array()));
            fileInputStream.close();
        }
    }

    4:使用一个 Buffer 完成文件读取、写入

      实例要求:

      1)   使用  FileChannel(通道)  和  方法       read , write,完成文件的拷贝

      2)   拷贝一个文本文件  1.txt      ,  放在项目下即可

      3)   代码演示

    package com.example.netty.nio;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class NIOFileChannel03 {
        public static void main(String[] args) throws Exception {
    
            FileInputStream fileInputStream = new FileInputStream(new File("d://file01.txt"));
            FileChannel fileInputStreamChannel = fileInputStream.getChannel();
    
            FileOutputStream fileOutputStream = new FileOutputStream(new File("d://file02.txt"));
            FileChannel fileOutputStreamChannel = fileOutputStream.getChannel();
    
            ByteBuffer byteBuffer = ByteBuffer.allocate(512);
    
            while (true) {  //循环读取
                int read = fileInputStreamChannel.read(byteBuffer);
                System.out.println("read:" + read);
                if (read == -1) {   //表示读完
                    break;
                }
                //将buffer中的数据写入到    fileOutputStreamChannel -- 2.txt
                byteBuffer.flip();
                fileOutputStreamChannel.write(byteBuffer);
                byteBuffer.clear();
            }
    
            fileInputStream.close();
            fileOutputStream.close();
        }
    }

    5:拷贝文件 transferFrom  方法

      1)   实例要求:

      2)   使用  FileChannel(通道)  和  方法       transferFrom  ,完成文件的拷贝

      3)   拷贝一张图片

      4)   代码演示

    package com.example.netty.nio;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.channels.FileChannel;
    
    public class NIOFileChannel04 {
        public static void main(String[] args) throws IOException {
            //创建相关流
            FileInputStream fileInputStream = new FileInputStream("d://1.jpg");
            FileOutputStream fileOutputStream = new FileOutputStream("d://2.jpg");
    
            //获取各个流对应的fileChannel
            FileChannel fileInputStreamChannel = fileInputStream.getChannel();
            FileChannel fileOutputStreamChannel = fileOutputStream.getChannel();
    
            //使用transferForm完成拷贝
            fileOutputStreamChannel.transferFrom(fileInputStreamChannel, 0 , fileInputStreamChannel.size());
    
            //关闭相关通道和流
            fileInputStream.close();
            fileOutputStream.close();
        }
    }

     6. 关于 Buffer  和  Channel 的注意事项和细节:

      1)   ByteBuffer  支持类型化的 put  和  get, put  放入的是什么数据类型,get 就应该使用相应的数据类型来取出,否

    则可能有  BufferUnderflowException  异常。[举例说明]

    package com.example.netty.nio;
    
    import java.nio.ByteBuffer;
    //java.nio.BufferUnderflowException:Buffer内存溢出异常
    public class NIOByteBufferPutGet {
        public static void main(String[] args) {
            //创建一个Buffer
            ByteBuffer buffer = ByteBuffer.allocate(64);
    
            //类型化方式放入数据
            buffer.putInt(100);
            buffer.putLong(1L);
            buffer.putShort((short) 4);
            buffer.putChar('上');
    
            //取出
            buffer.flip();
    
            System.out.println(buffer.getInt());
            System.out.println(buffer.getLong());
            System.out.println(buffer.getShort());
            System.out.println(buffer.getChar());
            System.out.println(buffer.getChar());
        }
    }

      2)   可以将一个普通 Buffer  转成只读 Buffer [举例说明]

    package com.example.netty.nio;
    
    import java.nio.ByteBuffer;
    //java.nio.ReadOnlyBufferException:Buffer只读异常
    public class ReadOnlyBuffer {
        public static void main(String[] args) {
            //创建Buffer
            ByteBuffer buffer = ByteBuffer.allocate(64);
    
            for (int i = 0; i < 64; i++) {
                buffer.put((byte) i);
            }
    
            //读取
            buffer.flip();
    
            //得到一个只读Buffer
            ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
            System.out.println(readOnlyBuffer.getClass());
    
            //读取
            while (readOnlyBuffer.hasRemaining()) {
                System.out.println(readOnlyBuffer.get());
            }
    
            readOnlyBuffer.put((byte) 1);   //java.nio.ReadOnlyBufferException
        }
    }

      3)   NIO  还提供了  MappedByteBuffer,  可以让文件直接在内存(堆外的内存)中进行修改,  而如何同步到文件,由 NIO  来完成. [举例说明]

    package com.example.netty.nio;
    
    import java.io.RandomAccessFile;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    /*
    说明:
    1. MappedByteBuffer  可让文件直接在内存(堆外内存)修改,  操作系统不需要拷贝一次
    */
    public class MappedByteBufferTest {
        public static void main(String[] args) throws Exception {
            RandomAccessFile randomAccessFile = new RandomAccessFile("d://1.txt", "rw");
    
            //获取相应的通道
            FileChannel channel = randomAccessFile.getChannel();
    
            /**
             *  参数 1: FileChannel.MapMode.READ_WRITE  使用的读写模式
             *  参数 2:  0  :  可以直接修改的起始位置
             *  参数 3:    5:  是映射到内存的大小(不是索引位置) ,即将  1.txt  的多少个字节映射到内存
             *  可以直接修改的范围就是  0-5
             *  实际类型  DirectByteBuffer
             */
            MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
    
            mappedByteBuffer.put(0, (byte) 'H');
            mappedByteBuffer.put(2, (byte) '9');
            mappedByteBuffer.put(5, (byte) '9');//java.lang.IndexOutOfBoundsException:索引越界异常
    
            randomAccessFile.close();
            System.out.println("文件修改完成!");
        }
    }

      4)   前面我们讲的读写操作,都是通过一个 Buffer  完成的,NIO  还支持  通过多个 Buffer (即  Buffer  数组)  完成读写操作,即  Scattering  和  Gathering  【举例说明】

  • 相关阅读:
    Java内存模型之重排序
    JAVA虚拟机:对象的创建过程
    单链表——基本操作
    new File()
    JVM回收方法区内存
    强软弱虚---强引用、软引用、弱引用、虚引用
    线性表(二)——链式存储
    JVM中判断对象是否存活的方法
    GC算法 垃圾收集器
    线性表(一)——顺序结构
  • 原文地址:https://www.cnblogs.com/luliang888/p/12410664.html
Copyright © 2020-2023  润新知