• Java IO学习总结(四)


    一、NIO

          NIO采用内存映射文件的方式来处理输入输出流,将文件或者文件的一段区域映射到内存中,这样就可以像访问内存一样访问文件,处理速度比传统的输入输出流要快。最主要的两个核心对象是Channel(通道)和Buffer(缓冲)。

    1)Buffer

         Buffer是一个抽象类,最主要的实现类是ByteBuffer,其他基本数据类型都有对应的buffer类。常用ByteBuffer和CharBuffer;

         创建一个Buffer对象,通过static XXBuffer allocate(int capacity)方法,capacity代表容量。

         Buffer中主要有三个重要的概念,容量(capacity)、界限(limit)和位置(position)

         容量:表示缓冲区的最大数据容量,不可以为负值,创建后不可以改变。

         界限:表示数据不可以被读出或者写入的缓冲区索引位置。

         位置:表示下一个可以被读出或者写入的缓冲区位置索引,当创建一个buffer对象之后,position为0,从中读取两条数据之后,position则为2,指向buffer中的第三个数据位置。写入时类似,position自动向后移动位置。

         Buffer中两个重要方法:flip()和clear();执行flip()方法之后,limit移动到position位置,position置为0,为输出数据做好准备,;执行clear()方法之后,limit移动到capacity位置,position位置置为0,为写入数据做好准备。

    Buffer常用操作示例代码:

    public class BufferTest {
        public static void main(String[] args) {
            // 创建Buffer
            CharBuffer buff = CharBuffer.allocate(10);
            
            // 初始化时:position位置为0,limit位置等于capacity
            System.out.println("缓冲区容量:" + buff.capacity());
            System.out.println("初始化position位置:" + buff.position());
            System.out.println("初始化limit位置:" + buff.limit());
            
            // 向缓冲区中放入三条数据
            buff.put('A');
            buff.put('B');
            buff.put('C');
            // 此时position位置为3,limit位置等于capacity
            System.out.println("装载数据时position位置:" + buff.position());
            System.out.println("装载数据时limit位置:" + buff.limit());
            
            // 装载数据结束
            buff.flip();
            // 查看此时position位置为0,limit位置为3
            System.out.println("装载数据完成position位置:" + buff.position());
            System.out.println("装载数据完成limit位置:" + buff.limit());
            
            // 取出数据,只有使用buff.get()方法时,position自动向后移动位置,使用buff.get(X)position位置不变。
            System.out.println("取出第一个数据" + buff.get());
            System.out.println("取出数据position位置:" + buff.position());
            
            // 取出数据完成
            buff.clear();
            // 查看此时position位置为0,limit位置等于capacity
            System.out.println("取出数据完成position位置:" + buff.position());
            System.out.println("取出数据完成limit位置:" + buff.limit());
        }
    }

    2)Channel

         Channel类似于传统的流对象,可以直接将指定文件的部分或者全部映射成Buffer,程序不能直接访问Channel,必须通过Buffer交互;所有的Channel都不能通过构造器来直接创建,而是通过传统的节点InputStream、OutStream的getChannel()的方法返回对于的Channel。

         Channel有三个主要的方法,map()、read()和write(),map()方法用于将Channel中数据映射成ByteBuffer.

    示例代码

    public class ChannelTest {
        public static void main(String[] args) {
            try {
                // 创建文件
                File file = new File("d:\test.txt");
                
                // 创建输入和输出Channel
                FileChannel fic = new FileInputStream(file).getChannel();    
                FileChannel foc = new FileOutputStream("d:\channel.txt").getChannel();
                
                // 将文件内容全部映射为ByteBuffer
                MappedByteBuffer buffer = fic.map(MapMode.READ_ONLY, 0, file.length());
                // 将buffer中数据之间输出到FileChannel中
                foc.write(buffer);
                // 初始化缓冲区
                buffer.clear();
                
                // 创建解码器用于buffer转换
                Charset charset = Charset.forName("GBK");
                CharsetDecoder cd = charset.newDecoder();
                
                // 将byteBuffer转换为charBuffer用于数据输出展示
                CharBuffer charbuff = cd.decode(buffer);
                System.out.println("数据为:" + charbuff);
                
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    另外一种读取方式

    public class ChannelTest1 {
        public static void main(String[] args) {
            try {
                File file = new File("d:\test.txt");
                FileChannel fci = new FileInputStream(file).getChannel();
                
                // 定义buffer
                ByteBuffer buff = ByteBuffer.allocate(256);
                
                while(fci.read(buff) != -1){
                    // 锁定缓存区域,防止读取null
                    buff.flip();
                    // 创建解码器转换为charbuffer输出
                    Charset charset = Charset.forName("GBK");
                    CharsetDecoder decode = charset.newDecoder();
                    System.out.println(decode.decode(buff));
                    
                    // 数据读取完之后,初始化缓冲区
                    buff.clear();
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    Linux安全-通过修改/etc/hosts.deny拒绝远程ssh暴力破解
    JS-二进制的处理者:Blob
    JS-二进制数据缓冲区ArrayBuffer
    axio源码分析
    【js】appendChild()具有移动性
    js实现-二进制数据转换为blob
    实现点击下载到本地的功能
    memo、useMemo、useCallback
    memoization缓存优化
    什么是纯函数?
  • 原文地址:https://www.cnblogs.com/quina520/p/7277451.html
Copyright © 2020-2023  润新知