java nio系列教程(2)---channel(通道介绍)和使用_messageutil.bytebuffertoarray-程序员宅基地

技术标签: JAVA  

大家推荐个靠谱的公众号程序员探索之路,公众号内点击网赚获取彩蛋,大家一起加油https://img-blog.csdnimg.cn/20181129224604602.png ​  

package com.zzh.buffer;

import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * 一.通道(channel):用于源节点与目标节点的连接.在java nio中负责缓冲区中数据的传输.channel本身不存储数据,因此需要配合缓冲区进行传输.
 * <p>
 * 二.通道的主要实现类
 * java.nio.channels.Channel接口:
 * |--FileChannel
 * |--SocketChannel
 * |--ServerSocketChannel
 * |--DatagramChannel
 * 三.获取通道
 * 1.java 针对支持通道的类提供了getChannel()方法
 * 本地IO:
 * FileInputStream/FileOutputStream
 * RandomAccessFile
 * <p>
 * 网络IO
 * Socket
 * ServerSocket
 * DatagramSocket
 * 2. 1.7之后 针对各个通道提供了静态方法open()
 * 3. 1.7后, Files工具类的newByteChannel
 */
public class TestChannel {

    public static void main(String[] args) {
        System.currentTimeMillis();

    }

    /**
     * 非直接缓冲区
     */
    @Test
    public void test1() {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            inputStream = new FileInputStream("1.jpg");
            outputStream = new FileOutputStream("2.jpg");
            //1.获取通道
            inChannel = inputStream.getChannel();
            outChannel = outputStream.getChannel();
            //分配缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            while (inChannel.read(byteBuffer) != -1) {
                //切换到读数据模式
                byteBuffer.flip();
                //将缓冲区中的数据写入通道中
                outChannel.write(byteBuffer);
                //清空缓冲区
                byteBuffer.clear();
            }
        } catch (Exception e) {

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

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

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

    /**
     * 内存映射文件
     */
    @Test
    public void test2() {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
            /**
             * 注意  StandardOpenOption.CREATE  CREATE_NEW  这两个的区别 create 不管之前是否存在都是创建一个   create_new 如果文件已存在就会报错
             */
            outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
            //这个内存映射文件是只读模式   从0开始  到inChannel.size()结束
            MappedByteBuffer inMap = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
            /**
             * 这个内存映射文件是读写模式   从0开始  到inChannel.size()结束
             * MappedByteBuffer没有单独的写模式 只有READ_WRITE读写模式 对应的通道StandardOpenOption 应该有读和写
             */
            MappedByteBuffer outMap = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

            byte[] bytes = new byte[inMap.limit()];
            inMap.get(bytes);
            outMap.put(bytes);
        } 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();
                }
            }
        }
    }

    /**
     * 通道之间的直接传输
     */
    @Test
    public void test3() {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
            /**
             * 注意  StandardOpenOption.CREATE  CREATE_NEW  这两个的区别 create 不管之前是否存在都是创建一个   create_new 如果文件已存在就会报错
             */
            outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

            /**
             * 输入通道   从0,开始到inChannel.size()结束,目标通道outChannel
             */
//            inChannel.transferTo(0, inChannel.size(), outChannel);
            /**
             * 输出通道  从inChannel通道来   0到inChannel.size()
             */
            outChannel.transferFrom(inChannel, 0, inChannel.size());
        } 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();
                }
            }
        }
    }

    /**
     * 分散(Scatter) 与 聚集(Gather)
     * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
     * 聚集写入(Gathering Writes):将多个缓冲区的数据聚集到通道中
     */
    @Test
    public void test4() {
        RandomAccessFile randomAccessFile = null;
        RandomAccessFile outFile = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            randomAccessFile = new RandomAccessFile("1.jpg", "rw");
            //获取通道
            inChannel = randomAccessFile.getChannel();

            //分配缓冲区
            ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);
            ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024);
            ByteBuffer[] byteBuffers = {byteBuffer1, byteBuffer2};

            //分散读取
            inChannel.read(byteBuffers);
            //切换到 读数据模式
            for (ByteBuffer byteBuffer : byteBuffers) {
                byteBuffer.flip();
            }

            outFile = new RandomAccessFile("3.jpg", "rw");
            outChannel = outFile.getChannel();
            //聚集写入
            outChannel.write(byteBuffers);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outFile != null) {
                try {
                    outFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

    /**
     * 尝试根据文件大小进行分散读取,聚集写入
     * @throws IOException
     */
    @Test
    public void test5() throws IOException{
        RandomAccessFile raf1 = new RandomAccessFile("1.jpg", "rw");
        //获取通道
        FileChannel channel1 = raf1.getChannel();
        //获取文件大小  单位是byte
        long size = channel1.size();
        //把大小分配到16个bytebuffer中  为什么是16个可以看下FileChannel的write方法可以发现 里面的循环 小于IOV_MAX=16
        int num = ((int)size / 16) + 1;
        List<ByteBuffer> byteBufferList = Lists.newArrayList();
        for (int i = 0;i < 16;i++){
            ByteBuffer buf = ByteBuffer.allocate(num);
            byteBufferList.add(buf);
        }
        //分散读取
        ByteBuffer[] bufs = new ByteBuffer[byteBufferList.size()];
        bufs = byteBufferList.toArray(bufs);
        channel1.read(bufs);
        //全部切换到读数据模式
        for (ByteBuffer byteBuffer : bufs) {
            byteBuffer.flip();
        }
        //聚集写入
        RandomAccessFile raf2 = new RandomAccessFile("5.jpg", "rw");
        FileChannel channel2 = raf2.getChannel();
        /**
         * 这里有个坑 不是所有的bufs都会写进去
         * 写的时候 for循环最大是16 也就是 bufs的16之后的都不会写进去
         */
        channel2.write(bufs);
    }

    /**
     * 字符集  编码与解码
     * 编码:字符串->字节数组
     * 解码:字节数组->字符串
     */
    @Test
    public void test6(){
        //所有字符集
//        SortedMap<String, Charset> map = Charset.availableCharsets();
//        for (Map.Entry<String, Charset> entity : map.entrySet()){
//            System.out.println(entity.getKey()+"--->"+entity.getValue());
//        }

        try {
            Charset gbk = Charset.forName("GBK");
            //获取编码器
            CharsetEncoder charsetEncoder = gbk.newEncoder();
            //获取解码器
            CharsetDecoder charsetDecoder = gbk.newDecoder();

            CharBuffer charBuffer = CharBuffer.allocate(1024);
            charBuffer.put("赵志恒");
            charBuffer.flip();
            //编码  解出来的bytebuffer已经是 切换成读模式了  不用在切换
            ByteBuffer encode = charsetEncoder.encode(charBuffer);
            //解码 解出来的CharBuffer已经是 切换成读模式了  不用在切换
            CharBuffer decode = charsetDecoder.decode(encode);
            System.out.println(decode.toString());
            Charset utf8 = Charset.forName("UTF-8");
            CharsetDecoder utf8Decoder = utf8.newDecoder();
            //encode 重置为可读
            encode.rewind();
            //此处这样并不能截出来 会抛出异常  MalformedInputException(此对象表示格式错误的输入错误)
            CharBuffer decode1 = utf8Decoder.decode(encode);
        } catch (CharacterCodingException e) {
            e.printStackTrace();
        } finally {
        }

    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yueloveme/article/details/84988010

智能推荐

Eureka的高可用_为什么有的公司不用euraka自己写高可用-程序员宅基地

文章浏览阅读201次。之前我们讲了如何将一个应用注册到Eureka上来,现在已经注册上来了,不知道大家有没有注意到一个问题,就是我们的Eureka他是一个单点,是单台服务器,假如这个Eureka他挂掉了怎么办呢,那你后续的操作不是都做不了了,这服务器还是很脆弱的,人都会挂,更何况服务器呢,所以我们要实现Eureka的高可用,这是我们目前的一个情况,单个client,往单个Eureka上注册,那我们要实现E..._为什么有的公司不用euraka自己写高可用

DW集训营算法基础梳理任务1:线性回归_一元线性回归模型dw表示什么-程序员宅基地

文章浏览阅读858次。【学习任务】线性回归损失函数的极大似然推导:西瓜书公式3.4除了用最小二乘法以外,怎么用极大似然推得?一元线性回归的参数求解公式推导:西瓜书公式3.7和3.8怎么推来的?多元线性回归的参数求解公式推导:西瓜书公式3.10和3.11怎么推来的?线性回归损失函数的最优化算法:什么是批量梯度下降、随机梯度下降、小批量梯度下降?一. 损失函数的极大似然推导要知道如何用极大似..._一元线性回归模型dw表示什么

javascript实现椭圆运动轨迹_js椭圆轨迹转动-程序员宅基地

文章浏览阅读2.9k次。 DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">html xmlns="http://www.w3.org/1999/xhtml" >head runat="server"> title>tit_js椭圆轨迹转动

stm32最小系统的PCB图_stm32最小系统pcb封装三维没有高度怎么办-程序员宅基地

文章浏览阅读500次。stm32最小系统的PCB图一、原理图封装添加二、PCB面板的生成三、原理图生成PCB的过程四、进行布局五、布线六、覆铜七、电气规则检查一、原理图封装添加连续点击两次原理图,出现右侧画面后点击添加点击浏览PCB封装库可以自己找资源或者自己创建,然后选择找资源查询资料寻找自己想要封装的类型,进行封装按t+g可以检查自己是否封装成功二、PCB面板的生成右键AD.prPCB三、原理图生成PCB的过程点击design下拉列表第一个,准备导入PCB如果没有错误,全是绿色的话,点击下方_stm32最小系统pcb封装三维没有高度怎么办

快速排序详解-程序员宅基地

文章浏览阅读10w+次,点赞155次,收藏538次。1.什么是快速排序我们知道排序有很多种,常见的如希尔排序,插入排序,选择排序,堆排序等等,而快速排序也是排序家族中的一员。因为其在大多数情况下有着优秀的综合性能,快速排序的快速也算是实至名归,接下来就为大家讲解快速排序的思想与实现。2.快速排序的核心思想快速排序通过多次比较与交换来完成排序。而这个过程又被分为了多次重复单趟排序,接下来我们先从每一趟的排序讲起。快速排序的单趟排序思想是:在一个无序数组中取一个数key,每一趟排序的最终目的是:让key的左边的所有数小于key,key的右边都_快速排序

HTML网页设计【足球科普】学生DW静态网页设计_运动科普网页设计-程序员宅基地

文章浏览阅读116次。网站布局方面:计划采用目前主流的、能兼容各大主流浏览器、显示效果稳定的浮动网页布局结构。网站程序方面:计划采用最新的网页编程语言HTML5+CSS3+JS程序语言完成网站的功能设计。并确保网站代码兼容目前市面上所有的主流浏览器,已达到打开后就能即时看到网站的效果。网站素材方面:计划收集各大平台好看的图片素材,并精挑细选适合网页风格的图片,然后使用PS做出适合网页尺寸的图片。网站文件方面:网站系统文件种类包含:html网页结构文件、css网页样式文件、js网页特效文件、images网页图片文件;..._运动科普网页设计

随便推点

Windows xp Ms08067漏洞复现_利用ms08-067漏洞控制xp建立不了回话-程序员宅基地

文章浏览阅读4k次。准备工作:虚拟机kaliWindows xp sp3中文版先ping双方的ip,以确保双方的网络可以互通nmap扫描Windows命令:cd /usr/share/nmap/scriptsnmap --script=vuln 192.168.XXX.XXX扫描后有漏洞ms08067用mts进行攻击先找漏洞利用:search 08_067运用漏洞:use exploit/windowsexploit/windows/smb/ms08_067_netapi看参数:show op_利用ms08-067漏洞控制xp建立不了回话

学习嵌入式系统需要具备的条件、方法及步骤-程序员宅基地

文章浏览阅读159次。1、将C和C++学好学精(语言层次); 2、将数据结构、算法、操作系统学扎实(内功层次); 3、爬山成功后,深入学习、理解、运用Windows或Linux核心编程。 下面是我转载的一些关于嵌入式的东西,对未来或许有些帮助和启示吧: 有些人以为搞嵌入式就是随便找本书看看,在电脑上编几个程序就完事。非也,其实嵌入式的门槛是比较高的。具体如下: 1、您得有一定数量的..._学习嵌入式系统获得的能力

移动支付之支付宝支付_mobilepayalipay-程序员宅基地

文章浏览阅读5.3k次。支付宝_mobilepayalipay

hibernate 注解字段默认值-程序员宅基地

文章浏览阅读866次。今天终于把这个问题给解决了。。呵呵,hibernate 注解字段默认值的设置: @Column(name="ISPUBLIC" ,nullable=false,columnDefinition="INT default 0") private int isPublic; 注意字段的类型必须指定,因为hibernate 会把columnDefinition 的内容直接写..._字段注解表示表默认值

Springboot毕设项目大连和平广场停车场管理系统52oca(java+VUE+Mybatis+Maven+Mysql)_停车场管理系统hbilder-程序员宅基地

文章浏览阅读65次。Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。Springboot + mybatis + Maven + Vue 等等组成,B/S模式 + Maven管理等等。2. 前端:vue+css+javascript+jQuery+easyUI+highcharts。2. 使用IDEA/Eclipse/MyEclipse导入项目,修改配置,运行项目;_停车场管理系统hbilder

每章一篇博客带你拿下吉林大学JAVAEE期末(一)_吉林大学javaee期末考试-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏38次。吉林大学JAVAEE课程PPT重要内容总结_吉林大学javaee期末考试