zoukankan      html  css  js  c++  java
  • 《疯狂Java讲义》(三十三)---- NIO

    • Buffer

    Buffer没有构造函数,只能通过static XxxBuffer allocate(int capacity) 来创建一个容量为capacity的XxxBuffer.

    package com.ivy.nio;
    
    import java.nio.CharBuffer;
    
    public class BufferDemo {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            CharBuffer buffer = CharBuffer.allocate(8);
            System.out.println("capacity:" + buffer.capacity());
            System.out.println("limit:" + buffer.limit());
            System.out.println("position:" + buffer.position());
            
            buffer.put("a");
            buffer.put("b");
            buffer.put("c");
            System.out.println("after adding three elements -------");
            System.out.println("position:" + buffer.position());
            buffer.flip();
            System.out.println("after flip -------");
            System.out.println("position:" + buffer.position());
            System.out.println("position(0):" + buffer.get());
            System.out.println("position:" + buffer.position());
            buffer.clear();
            System.out.println("after clear -------");
            System.out.println("limit:" + buffer.limit());
            System.out.println("position:" + buffer.position());
            System.out.println("position(2):" + buffer.get(2));
            System.out.println("position:" + buffer.position());
        }
    
    }

    三个重要概念,容量,界限,位置:

    1. 容量(capacity):缓冲区的容量,最多可以存多少数据。
    2. 界限(limit):第一个不应该被读出或写入的缓冲区位置索引,也就是说,位于limit后的数据既不可读,也不可写。
    3. 位置(position):用于指明下一个可以被读出的或写入到缓冲区位置索引,当读数据时,positon的值恰好等于已经读了多少数据。

    当Buffer装入数据解暑后,调用Buffer的flip方法,该方法将limit设置为position所在的位置,将position设为0,这样buffer就为输出数据做好了准备;当Buffer输出数据结束后,Buffer调用clear方法,它并不是清空数据,仅仅将position位置置为0,将limit置为capacity,这样为再次向Buffer中装入数据做好准备。

    • 使用Channel

    Channel类似于传统的流对象,但与传统的流对象有两个主要区别:

    1. Channel可以直接将制定文件的部分或全部直接映射成Buffer。
    2. 程序不能直接访问Channel的数据,包括读取,写入都不行,Channel只能与Buffer进行交互。

    所有的Channel都不应该通过构造器来直接创建,而是通过传统的节点InputStream,OutputStream的getChannel方法来返回对应的Channel,不同的节点流获得的Channel不一样。

    Channel中最常用的3个方法是map(), read()和write(). map()方法的方法签名为:MappedByteBuffer map(FileChannel.MapMode mode, long position, long size). 第一个参数执行映射时的模式,分别有只读/读写等模式,第二第三个参数用于控制将Channel的哪些数据映射成ByteBuffer。

    package com.ivy.nio;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.CharBuffer;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    
    public class FileChannelDemo {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            File f = new File("./src/com/ivy/nio/FileChannelDemo.java");
            try (
                    FileChannel inChannel = new FileInputStream(f).getChannel();
                    FileChannel outChannel = new FileOutputStream("channelOutput.txt").getChannel()) {
                MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
                Charset charset = Charset.forName("GBK");
                outChannel.write(buffer);
                buffer.clear();
                CharsetDecoder decoder = charset.newDecoder();
                CharBuffer charBuffer = decoder.decode(buffer);
                System.out.println(charBuffer);
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    
    }
    package com.ivy.nio;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class RandomFileChannelDemo {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            File f= new File("channelOutput.txt");
            try (
                    RandomAccessFile raf = new RandomAccessFile(f, "rw");
                    FileChannel randomChannel = raf.getChannel();) {
                
                MappedByteBuffer buffer = randomChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
                randomChannel.position(f.length());
                randomChannel.write(buffer);
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
                    
        }
    
    }
    • Charset
    package com.ivy.nio;
    
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.nio.charset.CharsetEncoder;
    
    
    public class CharsetTransformDemo {
    
        public static void main(String[] args) throws Exception {
            // TODO Auto-generated method stub
    
            Charset cn = Charset.forName("GBK");
            CharsetEncoder cnEncoder = cn.newEncoder();
            CharsetDecoder cnDecoder = cn.newDecoder();
            CharBuffer cBuffer = CharBuffer.allocate(8);
            cBuffer.put("孙");
            cBuffer.put("悟");
            cBuffer.put("空");
            cBuffer.flip();
            ByteBuffer bBuffer = cnEncoder.encode(cBuffer);
            for (int i = 0; i < bBuffer.capacity(); i++) {
                System.out.print(bBuffer.get(i)  + " ");
            }
            System.out.println("
    " + cnDecoder.decode(bBuffer));
        }
    
    }

    实际上,Charset类也提供了decode(ByteBuffer bb), encode(CharBuffer cb)和encode(String str),也就是说,获取了Charset对象后,如果仅仅需要进行简单的编码解码操作,其实无须创建CharsetEncoder & CharsetDecoder,直接调用Charst的encode和decode方法进行编码和解码就行。

    • 文件锁

    在NIO中,Java提供了FileLock来支持文件锁。

  • 相关阅读:
    北漂爱情[柒涩波]
    JavaScript基础知识五
    JavaScript基础知识四
    JavaScript基础知识三
    JavaScript基础知识二
    js内存泄漏
    CSS三列布局之左右宽度固定,中间元素自适应问题
    VScode 前端常用插件推荐
    将博客搬至CSDN
    python网络编程学习笔记(二)
  • 原文地址:https://www.cnblogs.com/IvySue/p/6404329.html
Copyright © 2011-2022 走看看