zoukankan      html  css  js  c++  java
  • Java -- 新IO -- 目录

        20.1 Java 新IO简介

        20.2 缓冲区与Buffer

          例:演示缓冲区的操作流程

          Class : IntBufferDemo01

          20.2.2 深入缓冲区操作

          20.2.3 创建子缓冲区

          20.2.4 创建只读缓冲区

          20.2.5 创建直接缓冲区

        20.3 通道

          20.3.1 FileChannel

            例:使用输出通道输出内容

            Class : FileChannelDemo01

    package lime.pri.limeNio._20_3_1.channeldemo;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class FileChannelDemo01 {
        public static void main(String[] args) throws Exception {
            String info[] = {"lime","oracle","Lime","Oracle"};
            File file = new File("F:/channels/out.txt");
            FileOutputStream output = null;
            output = new FileOutputStream(file);
            FileChannel fout = null;
            fout = output.getChannel();
            ByteBuffer buf = ByteBuffer.allocate(1024);
            for(int i = 0;i < info.length;i++){
                buf.put(info[i].getBytes());
                buf.put("
    ".getBytes());
            }
            buf.flip();
            fout.write(buf);
            fout.close();
            output.close();
        }
    }

            例:使用通道进行读写操作

            Class :FileChannelDemo02

    package lime.pri.limeNio._20_3_1.channeldemo;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class FileChannelDemo02 {
    
        public static void main(String[] args) throws Exception {
            File file1 = new File("F:/channels/note.txt");
            File file2 = new File("F:/channels/outnote.txt");
            FileInputStream input = null;
            FileOutputStream output = null;
            input = new FileInputStream(file1);
            output = new FileOutputStream(file2);
            FileChannel fin = null;
            FileChannel fout = null;
            fin = input.getChannel();
            fout = output.getChannel();
            ByteBuffer buf = ByteBuffer.allocate(1024);
            int temp = 0;
            while((temp = fin.read(buf)) != -1){
                buf.flip();
                fout.write(buf);
                buf.clear();
            }
            fin.close();
            fout.close();
            input.close();
            output.close();
        }
    }

          20.3.2 内存映射

            内存映射可以把文件映射到内存中,这样文件内的数据就可以用内存读/写指令来访问,而不是用InputStream或OutputStream这样的I/O操作类,采用此种方式读取文件的速度是最快的。

            提示:Java中访问文件内容的4中方法。

              ⊙ RandomAccessFile,随机读取数据,此种访问速度较慢。

              ⊙ FileInputStream,文件输入流,使用此种方式数度较慢。

              ⊙ 缓冲读取(例BufferedReader),使用此种方式访问速度较快。

              ⊙ 内存映射(MappedByteBuffer),使用此种方式读取速度最快。

            例:内存映射

            Class : FileChannelDemo03

    package lime.pri.limeNio._20_3_2.channeldemo;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class FileChannelDemo03 {
    
        public static void main(String[] args) throws Exception {
            File file = new File("F:/channels/mappedByteBuffer.txt");
            FileInputStream input = null;
            input = new FileInputStream(file);
            FileChannel fin = null;
            fin = input.getChannel();
            MappedByteBuffer mbb = null;
            mbb = fin.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            byte data[] = new byte[(int)file.length()];
            int foot = 0;
            while(mbb.hasRemaining()){
                data[foot++] = mbb.get();
            }
            System.out.println(new String(data));
            fin.close();
            input.close();
        }
    }

        20.4 文件锁:FileLock

          在Java新IO中提供了文件锁的功能,这样当一个线程将文件锁定之后,其他线程是无法操作此文件的。要想进行文件的锁定操作,则要使用FileLock类完成,此类的对象需要依靠FileChannel进行实例化操作。

          ⊙ 共享锁:允许多个线程进行文件的读取操作。

          ⊙ 独占锁:只允许一个线程进行文件的读/写操作。 

          例:将文件锁定

          Class : FileLockDemo

    package lime.pri.limeNio._20_4.channeldemo;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileLock;
    
    public class FileLockDemo {
    
        public static void main(String[] args) throws Exception {
            File file = new File("F:/channels/fileLock.txt");
            FileOutputStream output = null;
            output = new FileOutputStream(file,true);
            FileChannel fout = null;
            fout = output.getChannel();
            FileLock lock = fout.tryLock();
            if(lock != null){
                System.out.println(file.getName() + " 文件锁定300秒");
                Thread.sleep(300000);
                lock.release();
                System.out.println(file.getName() + " 文件解除锁定");
            }
            fout.close();
            output.close();
        }
    }

        20.5 字符集:Charset

          例:取得Charset类的全部编码

          Class : GetAllCharsetDemo

    package lime.pri.limeNio._20_5.channeldemo;
    
    import java.nio.charset.Charset;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.SortedMap;
    
    public class GetAllCharsetDemo {
    
        public static void main(String[] args) {
            SortedMap<String, Charset> all = null;
            all = Charset.availableCharsets();
            Iterator<Map.Entry<String,Charset>> iter = null;
            iter = all.entrySet().iterator();
            while(iter.hasNext()){
                Map.Entry<String, Charset> me = iter.next();
                System.out.println(me.getKey() + " --> " + me.getValue());
            }
        }
    }

          例:编码-解码操作

          Class : CharsetEnDeDemo

        20.6 Selector

          在新IO中Selector是一个极其重要的概念,在原来使用IO和Socket构造网络服务时,所有的网络服务经使用阻塞方式进行客户端的连接,而如果使用了新IO则可以构造一个非阻塞的的网络服务。

          Selector类的常用方法:

            ⊙ public static Selector open() throws IOException :  打开一个选择器。

            ⊙ public abstract int select() throws IOException : 选择一组键,其相应的通道已为 I/O 操作准备就绪。

            ⊙ public abstract Set<SelectionKey> selectedKeys() : 返回此选择器的已选择键集。

          在进行非阻塞网络开发时需要使用SelectableChannel类向Select类注册,而且在新IO中实现网络程序需要依靠ServerSocketChannel类与SocketChannel类,这两个类都是SelectableChannel的子类,SelectableChannel提供了注册Selector的方法和阻塞模式。

          ServerSocketChannel类的常用方法:

            ⊙ public final SelectableChannel configureBlocking(boolean block) throws IOException : 调整此通道的阻塞模式。true:阻塞模式;false:非阻塞模式

            ⊙ public final SelectionKey register(Selector sel, int ops) throws ClosedChannelException :  向给定的选择器注册此通道,返回一个选择键。

            ⊙ public static ServerSocketChannel open() throws IOException : 打开服务器的套接字通道。

            ⊙ public abstract ServerSocket socket() : 返回与此通道关联的服务器套接字。

          在使用register()方法时需要指定一个选择器(Selector对象)以及Select域,Selector对象可以通过Selector中的open()方法取得,而Selector域则在SelectionKey类中定义。

          4中Selector域:

            ⊙ public static final int OP_ACCEPT   = 1 << 4: 相当于ServerSocket中的accpet()操作。

            ⊙ public static final int OP_CONNECT  = 1 << 3 :连接操作。 

            ⊙ public static final int OP_READ = 1 << 0 : 读操作。

            ⊙ public static final int OP_WRITE = 1 << 2 : 写操作。

          如果要使用服务器想客户端发送信息,则需要通过SelectionKey类中提供的方法判断服务器的操作状态。而要想取得客户端的连接也需要使用SelectionKey类。

          SelectionKey常用的方法:

            ⊙ public abstract SelectableChannel channel() : 返回为之创建此键的通道。

            ⊙ public final boolean isAcceptable() : 测试此键的通道是否已准备好接受新的套接字连接。

            ⊙ public final boolean isConnectable() : 测试此键的通道是否已完成其套接字连接操作。

            ⊙ public final boolean isReadable() : 测试此键的通道是否已准备好进行读取。

            ⊙ public final boolean isWritable() : 测试此键的通道是否已准备好进行写入。

          例:取得时间的服务器

          Class : DateServer

    package lime.pri.limeNio._20_6.channeldemo.selector;
    
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Date;
    import java.util.Iterator;
    import java.util.Set;
    
    public class DateServer {
    
        public static void main(String[] args) throws Exception {
            int ports[] = {8000,8001,8002,8003,8005,8006};    //定义一组连接端口号
            Selector selector = Selector.open();    //打开一个选择器
            for(int i = 0;i < ports.length;i++){    //构造服务器的启动信息
                ServerSocketChannel initSer = null;    //声明ServerSocketChannel
                initSer = ServerSocketChannel.open();    //打开服务器套接字通道
                initSer.configureBlocking(false);    //服务器配置为非阻塞
                ServerSocket initSock = initSer.socket();    //检索此通道关联的服务器套接字
                InetSocketAddress address = null;    //表示监听地址
                address = new InetSocketAddress(ports[i]);    //实例化绑定地址
                initSock.bind(address);    //绑定地址
                //注册选择器,相当于使用accept()方法接收
                initSer.register(selector, SelectionKey.OP_ACCEPT);
                System.out.println("服务器运行,在 " + ports[i] + " 端口监听。");
            }
            int keysAdd = 0;    //接收一组SelectionKey
            while((keysAdd = selector.select()) > 0){    //选择一组键,相应的通道已为IO准备就绪
                Set<SelectionKey> selectedkeys = selector.selectedKeys();    //取出全部生成的key
                Iterator<SelectionKey> iter = selectedkeys.iterator();    //实例化Iterator
                while(iter.hasNext()){    //迭代全部的key
                    SelectionKey key = (SelectionKey)iter.next();    //取出每一个SelectionKey
                    if(key.isAcceptable()){    //判断客户端是否已经连接上
                        ServerSocketChannel server = (ServerSocketChannel)key.channel();    //取得Channel
                        SocketChannel client = server.accept();    // 接收新连接
                        client.configureBlocking(false);    //设置成非阻塞状态
                        ByteBuffer outBuf = ByteBuffer.allocateDirect(1024);    //开辟缓冲区
                        outBuf.put(("当前时间为:" + new Date()).getBytes());    //缓冲区设置内容
                        outBuf.flip();    //重置缓冲区
                        client.write(outBuf);    //输出信息
                        client.close();    //关闭输出流
                    }
                }
                selectedkeys.clear();    //清除全部key
            }
        }
    }

          Console : telnet 

        啦啦啦

  • 相关阅读:
    English trip -- VC(情景课)1 A Get ready
    隔板法总结
    CF 题目选做
    ZROI 提高十连测 DAY2
    2019 09 05
    线性基总结
    解决痛苦的方法/cy
    梅深不见冬 树上贪心
    ZROI 提高十连测 Day1
    [USACO09NOV]硬币的游戏 博弈 dp
  • 原文地址:https://www.cnblogs.com/ClassNotFoundException/p/6985577.html
Copyright © 2011-2022 走看看