zoukankan      html  css  js  c++  java
  • NIO--通道

    一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。

    二、通道的主要实现类
    java.nio.channels.Channel 接口:
    |--FileChannel
    |--SocketChannel
    |--ServerSocketChannel
    |--DatagramChannel

    三、获取通道
    1. Java 针对支持通道的类提供了 getChannel() 方法
    本地 IO:
    FileInputStream/FileOutputStream
    RandomAccessFile

    网络IO:
    Socket
    ServerSocket
    DatagramSocket

    2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
    3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()

    四、通道之间的数据传输
    transferFrom()
    transferTo()

    五、分散(Scatter)与聚集(Gather)
    分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
    聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中

    六、字符集:Charset
    编码:字符串 -> 字节数组
    解码:字节数组 -> 字符串

    public class TestChannel {

    //字符集
    @Test
    public void test6() throws IOException{
    Charset cs1 = Charset.forName("GBK");

    //获取编码器
    CharsetEncoder ce = cs1.newEncoder();

    //获取解码器
    CharsetDecoder cd = cs1.newDecoder();

    CharBuffer cBuf = CharBuffer.allocate(1024);
    cBuf.put("尚硅谷威武!");
    cBuf.flip();

    //编码
    ByteBuffer bBuf = ce.encode(cBuf);

    for (int i = 0; i < 12; i++) {
    System.out.println(bBuf.get());
    }

    //解码
    bBuf.flip();
    CharBuffer cBuf2 = cd.decode(bBuf);
    System.out.println(cBuf2.toString());

    System.out.println("------------------------------------------------------");

    Charset cs2 = Charset.forName("GBK");
    bBuf.flip();
    CharBuffer cBuf3 = cs2.decode(bBuf);
    System.out.println(cBuf3.toString());
    }

    @Test
    public void test5(){
    Map<String, Charset> map = Charset.availableCharsets();

    Set<Entry<String, Charset>> set = map.entrySet();

    for (Entry<String, Charset> entry : set) {
    System.out.println(entry.getKey() + "=" + entry.getValue());
    }
    }

    //分散和聚集
    @Test
    public void test4() throws IOException{
    RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");

    //1. 获取通道
    FileChannel channel1 = raf1.getChannel();

    //2. 分配指定大小的缓冲区
    ByteBuffer buf1 = ByteBuffer.allocate(100);
    ByteBuffer buf2 = ByteBuffer.allocate(1024);

    //3. 分散读取
    ByteBuffer[] bufs = {buf1, buf2};
    channel1.read(bufs);

    for (ByteBuffer byteBuffer : bufs) {
    byteBuffer.flip();
    }

    System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
    System.out.println("-----------------");
    System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));

    //4. 聚集写入
    RandomAccessFile raf2 = new RandomAccessFile("2.txt", "rw");
    FileChannel channel2 = raf2.getChannel();

    channel2.write(bufs);
    }

    //通道之间的数据传输(直接缓冲区)
    @Test
    public void test3() throws IOException{
    FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);
    FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

    // inChannel.transferTo(0, inChannel.size(), outChannel);
    outChannel.transferFrom(inChannel, 0, inChannel.size());

    inChannel.close();
    outChannel.close();
    }

    //使用直接缓冲区完成文件的复制(内存映射文件)
    @Test
    public void test2() throws IOException{//2127-1902-1777
    long start = System.currentTimeMillis();

    FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);
    FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

    //内存映射文件
    MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
    MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());

    //直接对缓冲区进行数据的读写操作
    byte[] dst = new byte[inMappedBuf.limit()];
    inMappedBuf.get(dst);
    outMappedBuf.put(dst);

    inChannel.close();
    outChannel.close();

    long end = System.currentTimeMillis();
    System.out.println("耗费时间为:" + (end - start));
    }

    //利用通道完成文件的复制(非直接缓冲区)
    @Test
    public void test1(){//10874-10953
    long start = System.currentTimeMillis();

    FileInputStream fis = null;
    FileOutputStream fos = null;
    //①获取通道
    FileChannel inChannel = null;
    FileChannel outChannel = null;
    try {
    fis = new FileInputStream("d:/1.mkv");
    fos = new FileOutputStream("d:/2.mkv");

    inChannel = fis.getChannel();
    outChannel = fos.getChannel();

    //②分配指定大小的缓冲区
    ByteBuffer buf = ByteBuffer.allocate(1024);

    //③将通道中的数据存入缓冲区中
    while(inChannel.read(buf) != -1){
    buf.flip(); //切换读取数据的模式
    //④将缓冲区中的数据写入通道中
    outChannel.write(buf);
    buf.clear(); //清空缓冲区
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if(outChannel != null){
    try {
    outChannel.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    if(inChannel != null){
    try {
    inChannel.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    if(fos != null){
    try {
    fos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    if(fis != null){
    try {
    fis.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    long end = System.currentTimeMillis();
    System.out.println("耗费时间为:" + (end - start));

    }

    }

  • 相关阅读:
    1.4.2.3. SETUP(Core Data 应用程序实践指南)
    1.4.2.2. PATHS(Core Data 应用程序实践指南)
    1.4.2.1. FILES(Core Data 应用程序实践指南)
    1.4.2. 实现 Core Data Helper 类(Core Data 应用程序实践指南)
    1.4.1. Core Data Helper 简介(Core Data 应用程序实践指南)
    1.4. 为现有的应用程序添加 Core Data 支持(Core Data 应用程序实践指南)
    1.3.2. App Icon 和 Launch Image(Core Data 应用程序实践指南)
    1.3.1. 新建Xcode项目并设置故事板(Core Data 应用程序实践指南)
    php验证邮箱是否合法
    如何使js函数异步执行
  • 原文地址:https://www.cnblogs.com/keleaiww/p/10979800.html
Copyright © 2011-2022 走看看