范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

javaNIO学习笔记(二)

  javaNIO 学习笔记(二)
  参考文档:http://tutorials.jenkov.com/java-nio/channels.html Java NIO Channel
  和传统的IO中的  InputStream  、OutputStream  相比,主要区别就是传统IO中的stream是单向的。但是在NIO中的channel  是可读可写的。并且读写是可以异步进行的。另外channel  都是从buffer  中读取或者写入数据的
  上一篇学习笔记中的主要实现的管道类型 FileChannel 从文件和文件读取数据 DatagramChannel 可以通过UDP在网络上读写数据。 SocketChannel 可以通过TCP在网络上读写数据。 ServerSocketChannel 允许您侦听传入的TCP连接,就像web服务器一样。为每个传入连接创建SocketChannel。
  这4个类在idea中可以查看相应的UML图 FileChannel
  先看下面的程序
  读取文件数据: public class FileChannelPrc {      public static void main(String[] args) throws IOException {         // 创建一个rw模式的随机文件         RandomAccessFile randomAccessFile =new RandomAccessFile("D:nioFile.txt", "rw");         // 获取fileChinnel         FileChannel fileChannel = randomAccessFile.getChannel();          // 设定缓冲区大小48         ByteBuffer buf = ByteBuffer.allocate(48);                  int bytesRead = fileChannel.read(buf);         while(bytesRead !=-1){             System.out.println(" Read " + bytesRead);                          buf.flip();              while(buf.hasRemaining()){                 System.out.print((char) buf.get());             }              buf.clear();             bytesRead = fileChannel.read(buf);         }         randomAccessFile.close();     } }  // 运行结果: Hi, I am jimmy.
  上面程序要正确执行需要,先在本地对应文件夹中创建相应文件。我在文件中写入的是 Hi, I am jimmy.  这里就可以看到读取出来并且打印了。
  然后我们将文件内容修改为 Hi, I am jimmy. I am learning Java NIO. Hope I can hold it.  (大于48字符)。在运行程序,此时返回值
  Read 48
  Hi, I am jimmy. I am learning Java NIO. Hope I
  Read 13
  can hold it.
  通过上面的测试我们大概可以猜测。 // 通过fileChannel将数据读取到缓冲区,返回值是缓冲区读取的字节数 int bytesRead = fileChannel.read(buf); // 判断缓冲区是否还有数据 buf.hasRemaining() // 获取当前缓冲区的第一个元素 buf.get() // 切换缓冲区读写模式     buf.flip(); // 清空缓存区 buf.clear();
  我们现在先只来看 channel  相关的猜测。改造程序(改造部分如下)// 设定缓冲区大小 ByteBuffer buf = ByteBuffer.allocate(48); ByteBuffer buf2 = ByteBuffer.allocate(48); int bytesRead = fileChannel.read(buf); int bytesRead2 = fileChannel.read(buf); System.out.println("bytesRead" + bytesRead + "  bytesRead2" + bytesRead2);
  此时走debug或者查看打印语句就可以看出来, bytesRead = 16 bytesRead2 = -1  (文件信息Hi, I am jimmy.  )。那么这样就可以得出一个结论
  fileChannel.read(buf);会将 channel  的数据flush  到缓冲区,而不是复制。
  下面是程序则是使用fileChannel写信息到文件中 public class FileChannelPrc {      public static void main(String[] args) throws IOException {                 ...         // 写文件 //        ByteBuffer buf2 = ByteBuffer.allocate(48);         String newData = "do not worry, be happy 时间:" + System.currentTimeMillis();         buf.clear();         buf.put(newData.getBytes());         while(buf.hasRemaining()) {              buf.flip();             fileChannel.write(buf);         }          fileChannel.close();         randomAccessFile.close();     } }
  查看文件,文件文本显示
  Hi, I am jimmy. do not worry, be happy 时间:1591970658685
  看这样的结果可以看出来, fileChannel  写数据的时候是在文件结尾处增加写入数据,而非覆盖。
  那么根据上面的例子我们先简单地总结下 fileChannel  简单使用方法。获取fileChannel的实例(注意 public abstract class FileChannel  这是个抽象类),获得方式
  可以使用 RandomAccessFile  的实例来获取读取数据的方法使用 read  将内容读取到ByteBuffer  ,当然这里也涉及ByteBuffer  的使用,这个后面在学习总结写过程呢则是使用 write  方法向文件写入ByteBuffer  的信息。当然最后和传统IO一样,需要调用 close  来关闭fileChannel
  接下来稍微看下 fileChannel  的源码(这里也算是写一个备忘录,以后遇到相关问题的时候可以回来看下,或许会有帮助)// ----   read方法   ------- public abstract int read(ByteBuffer dst) throws IOException; // 从指定位置开始读取数据 public abstract int read(ByteBuffer dst, long position) throws IOException; public final long read(ByteBuffer[] dsts) throws IOException {         return read(dsts, 0, dsts.length); } public abstract long read(ByteBuffer[] dsts, int offset, int length) throws IOException;  // ------  write方法  ------ public abstract int write(ByteBuffer src) throws IOException; public abstract int write(ByteBuffer src, long position) throws IOException; public final long write(ByteBuffer[] srcs) throws IOException {     return write(srcs, 0, srcs.length); } public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException;  // ---- open方法 ------  @since   1.7  这个方法可以获取fileChannel public static FileChannel open(Path path, OpenOption... options) throws IOException {     Set set = new HashSet(options.length);     Collections.addAll(set, options);     return open(path, set, NO_ATTRIBUTES); } public static FileChannel open(Path path,  Set<? extends OpenOption> options,                                    FileAttribute<?>... attrs) throws IOException {     FileSystemProvider provider = path.getFileSystem().provider();     return provider.newFileChannel(path, options, attrs); }  // ---  position  -- // 获取一个新的fileChannel  public abstract FileChannel position(long newPosition) throws IOException; // 返回buffer读取的位置 public abstract long position() throws IOException; // --- force  ---- // 强制将channel的数据写入,根据metaData决定是否写入本地磁盘存储 public abstract void force(boolean metaData) throws IOException; // Returns the current size of this channel"s file. 返回当前通道中的文件大小 public abstract long size() throws IOException; // 截取指定长度的数据,从开始进行截取长度为 size的 public abstract FileChannel truncate(long size) throws IOException;
  当然还有一些其他方法,这些等以后涉及使用的时候在补充吧。这里附上测试的时候的代码(非全部,有的API直接可使用idea的片段执行查看结果。) public class FileChannelPrc {      public static void main(String[] args) throws IOException {         // 创建一个rw模式的随机文件         RandomAccessFile randomAccessFile =new RandomAccessFile("D:nioFile.txt", "rw");         // 获取fileChinnel         FileChannel fileChannel = randomAccessFile.getChannel();  //        fileChannel.position();         FileChannel fileChannel2 = fileChannel.truncate(10);         // 设定缓冲区大小         ByteBuffer buf = ByteBuffer.allocate(48);  //        int bytesRead = fileChannel.read(buf,10L);         int bytesRead = fileChannel2.read(buf);  //        ByteBuffer buf2 = ByteBuffer.allocate(48);  //        int bytesRead = fileChannel.read(buf);         /*int bytesRead2 = fileChannel.read(buf);         System.out.println("bytesRead" + bytesRead + "  bytesRead2" + bytesRead2);*/         while(bytesRead !=-1){             System.out.println("Read " + bytesRead);             buf.flip();              while(buf.hasRemaining()){                 System.out.print((char) buf.get());             }              buf.clear(); //            bytesRead = fileChannel.read(buf);             bytesRead = fileChannel2.read(buf);         }          // 写文件 //        ByteBuffer buf2 = ByteBuffer.allocate(48);        /* String newData = "do not worry, be happy 时间:" + System.currentTimeMillis();         buf.clear();         buf.put(newData.getBytes());         while(buf.hasRemaining()) {             buf.flip();             fileChannel.write(buf);         }*/          fileChannel.close();         randomAccessFile.close();     } }  SocketChannel 和 ServerSocketChannel
  socketChannel  是一个用来处理TCP网络套接字的通道。有两种方式来获取SocketChannel  使用open()可以直接获取一个实例 通过 ServerSocketChannel  来获取SocketChannel socketChannel = SocketChannel.open();
  ServerSocketChannel  类似于标准Java网络中的ServerSocket  一样,是一个可以侦听传入TCP连接的通道.ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
  no talk,show code package jniolearn.channel;  import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel;  /**  * @Author: jimmy  * @Date: 2020/6/13 15:03  * @Description:  *  * 理解为server  */ public class ServerSocketChannelPrc {      public static void main(String[] args) throws IOException {          // 获取实例         ServerSocketChannel server = ServerSocketChannel.open();         // 绑定ip和端口         server.socket().bind(new InetSocketAddress("127.0.0.1",2999));         //设置为非阻塞模式         server.configureBlocking(false);         // 获取 SocketChannel         while(true){             SocketChannel serverChannel =  server.accept();              if(serverChannel != null) {                 ByteBuffer buf = ByteBuffer.allocate(512);                 int byteRead = serverChannel.read(buf);                  StringBuilder req = new StringBuilder();                 buf.flip();                 while(buf.hasRemaining()){                     req.append((char) buf.get());                 }                 buf.clear();                  System.out.println("客户端发来消息" + req);                  buf.put("hi,this is jimmy. be happy ".getBytes());                 buf.flip();                 serverChannel.write(buf);      //        serverChannel.close();             }         }     } }   package jniolearn.channel;  import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel;  /**  * @Author: jimmy  * @Date: 2020/6/13 12:04  * @Description:  *  * 可以理解为client  */ public class SocketChannelPrc {      /**      * 为了方便,这里直接将异常抛出,实际开发要进行异常捕捉      * @param args      * @throws IOException      */     public static void main(String[] args) throws IOException {          //  获取 SocketChannel 的实例         SocketChannel client = SocketChannel.open();         /**          * 连接服务端,这里面传入的参数对象为 SocketAddress          * 查看源码可以找到一个实现类 InetSocketAddress 构造方法 public InetSocketAddress(String hostname, int port)          * 看到这个构造就很熟悉了,          *          * 连接服务  127.0.0.1 和 2999 端口          */         client.connect(new InetSocketAddress("127.0.0.1",2999));          // 有channel就需要有缓冲区buffer         ByteBuffer buf = ByteBuffer.allocate(512);         buf.put("hi, jimmy,this is client.".getBytes());         // 切换读写模式         buf.flip();         // 写数据去服务器         client.write(buf);         // 清空buffer,此时相当于将buffer重置为读模式         buf.clear();         int byteRead =  client.read(buf);         buf.flip();         StringBuilder stringBuffer=new StringBuilder();         while (buf.hasRemaining()){             stringBuffer.append((char) buf.get());         }         buf.clear();          System.out.println("从服务端接收到的数据:"+stringBuffer);          // 关闭 socketChannel         client.close();     } }
  先启动服务端 ServerSocketChannel  ,然后U启动SocketChannel  .返回结果如下:客户端发来消息hi, jimmy,this is client.  从服务端接收到的数据:hi,this is jimmy. be happy
  整体看来和 fileChannel  差不太多,基本都是要先有一个打开的channel  (有一个方法是isOpen()可以获取是否打开)。然后使用相应的缓冲区来将数据从通道写入缓冲区或者从缓冲区读取数据。(关于buffer相关的方法后面在学习)。不过要注意一些特别的地方SocketChannel``ServerSocketChannel  的一个方法configureBlocking()  这个方法表示这个SocketChannel``ServerSocketChannel  是阻塞还是非阻塞的,具体使用方式等学习了selector  的时候在进行补充。当然上面程序是不完善的,接受放缓冲区不够大的时候会报错。具体可以改下代码看看。DatagramChannel
  DatagramChannel  类似于java 网络编程的DatagramSocket类;使用UDP进行网络传输
  同样的可以使用open方法获取一个实例 package jniolearn.channel;  import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel;  /**  * @Author: jimmy  * @Date: 2020/6/13 17:32  * @Description:  * server  */ public class DatagramChannelPrcS {      public static void main(String[] args) throws IOException {         DatagramChannel s = DatagramChannel.open();         s.bind(new InetSocketAddress("127.0.0.1",3999));         ByteBuffer buf = ByteBuffer.allocate(48);         s.receive(buf);         buf.clear();         while(buf.hasRemaining()){             System.out.print((char)buf.get());         }      } }  package jniolearn.channel;  import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel;  /**  * @Author: jimmy  * @Date: 2020/6/13 17:26  * @Description:  * client  */ public class DatagramChannelPrc {      public static void main(String[] args) throws IOException {          DatagramChannel channel = DatagramChannel.open();         // 绑定端口 //        channel.bind(new InetSocketAddress(3999));          ByteBuffer buf = ByteBuffer.allocate(48);         buf.put("datagrameChannel info".getBytes());         // datagrameChannel不需要使用这个方法 //        channel.write(buf);         buf.flip();         int a = channel.send(buf,new InetSocketAddress("127.0.0.1",3999));         channel.close();     } }
  使用起来比较简单,服务端可以直接使用bind方法绑定端口、ip。客户端从缓冲区直接将数据发哦是那个至服务器。是否发送成功或者成功被接收到是没有保证的;发送消息通过send方法发出,改方法返回一个int值,表示成功发送的字节数:
  那么这学习留下一个尾巴就是关于阻塞模式和非阻塞模式的区别以及应用。这个在学习完其他类之后在进行补充学习

助听器一定要双耳配同款的吗?对听力有障碍的人,选配助听器一事,在我陪父亲去专卖店,选配6年中的体会,一开始仅配一个耳背式助听器,但随着老人年龄的增长,听力逐步减弱,我认为双耳都配戴,听力效果显得更好。助听器随戴助听器会不会听到吵的声音会头晕?导致头晕的可能性1。初次佩戴,出现不适应的现象。2。助听器的性能比较简单,对噪音处理不好,嘈杂环境吵得头晕。3。调试的问题,增益给的过大,也会吵得头晕现在助听器都是根据听力和需求精火星着陆遭国外质疑,祝融号传回着陆影像,为何数据接收这么久?他质疑或者是相信,跟我们没关系,只要你别跟着瞎起哄就行祝融号登陆火星的前两天并没有与天问一号轨道器建立数据链路,而是采用直传地球的方式,传输速率最高16Bs。主要是回传工程参数。现想买一部流畅,护眼的手机,求推荐,5000以下的?5000元这个价位卡得很死,苹果新款就不用想了,甚至连华为Mate40Pro小米11Ultra这样顶级的安卓旗舰也买不到。不过可以考虑以下几款手机第一款vivoX60Pro这应该是新买的手机上面的原厂膜你们会不会撕掉?现在大部分手机都会贴上原厂膜了,最开始是OPPOvivo带头,华为在经历了疏油层门之后也给手机贴了原厂膜。就连一向比较抠门的小米,这两年的新机也都贴上了出厂膜。对于这层膜,我个人的为什么京东卖的小米手机比小米官网还便宜?不请自来,还望勿怪。因为经常在京东上买购买手机的缘故,所以对渠道这方面的问题还是比较了解的,所以就让我来为大家解答一下吧。京东是小米手机的授权经销商,拿货的量大,而且小米方面在网上那些催收人是怎么搞到欠款人的新号码的?01hr网络渠道找到的现在的网络媒体太发达了,每个人都有自己常用的网络社交工具。很多人都喜欢分享自己工作和生活中的点点滴滴,QQ空间朋友圈微博抖音等等社交网络工具中经常会更新我们的今日头条各种游戏广告都是轻松提现真的假的?首先,我们不能说是假的,为了验证是不是假的,我一口气下载了好几十个这类app,从二月到五月,总计4个月共收入276。24元说到这里,大家可能觉得这有点少,4个月确实少,但这只是平时烟花燃放产生的温度能不能消灭空气中的新冠病毒?新冠病毒最适合低温下生存,遇到高温活力变小或自取灭亡。这是经过科研人员,近一年来的摸索研究经过科学论断出来的真理。所以专家们才提醒人们,尽量不要接触那么多冷冻食品。特别是海产品和肉为何任正非宁可自损八百,也要围剿李一男?西方资本的渗入李一男对华为有多重要呢?当年他与郑宝用开发的万门机所使用的准SDH技术,至今仍然是国际通信技术的最高标准。有人说一个李一男,半部华为史,其实更确切地说一个李一男,半部中国通信史。李为什么中国所有手机厂商不一致启用鸿蒙操作系统来抵制谷歌?随着商务部最新出台的阻断法实施,国内各手机产品在中国境内继续使用安卓系统是要申请得到批准才行的,不过我认为商务部不会同意继续使用安卓,这样三星小米等手机在中国境内销售只能安装自研操
未售先火!RedmiNote10系列1小时销量突破50万台小米的实力向来都是不容小觑的,就今年发布的几款手机,每一款都饱受好评,深受消费者的喜爱。这些年小米在手机行业里已经是佼佼者了,不论是从手机的外观设计,还是性能方面,都做得很不错,消独家中国电信集团新增一名副总经理由广东电信总经理唐珂升任运营商财经吴碧慧文知情人士向运营商财经网独家透露,据最新消息,5月31日上午,广东电信总经理唐珂升任中国电信集团副总经理一职,至此,中国电信集团领导班子成员总算补了一人。唐珂升任中社区团购无序竞争再遭处罚,赛道战火将向供应链蔓延5月27日,市场监管总局对社区团购平台十荟团涉低价倾销诱骗消费者的行为处以150万元顶格罚款,江苏区域停业整顿3日。这已经是市场监管总局年内第二次点名社区团购平台。今年3月,十荟团先理想一步抢占主流市场,门槛更低的增程式电动,天际ME5来了理想ONE的成功,证明了拥增程式方案解决续航焦虑的可行性,即使理想ONE用的是三缸动力,电机性能也不出彩,甚至还在质量上出过不少问题,但这种槽点不少却依旧受欢迎的状况,愈加证明了增鸿蒙系统何去何从?由于美国特朗普政府封锁,华为已经失去了麒麟芯片的代工,华为的销量一路下降,虽然我们不愿意看到,但是事实就是如此残酷,没想到华为这样悲壮的告别手机领域,不过华为及时推出鸿蒙系统,让华苹果WWDC发布会苹果已预告过WWDC发布会将在六月份举办,苹果正式在官网发布了大会的邀请函。与往年不同的是,往年的WWDC大会仅有一天,而今年的大会足足持续5天!从6月8日一直持续到6月12日,今中国的操作系统应该什么样?华为鸿蒙2天后能给出答案么?历史上,全球对于操作系统的竞争一直都未停止。从三星先后发布的Bada,Tizen微软推出WindowsMobile再到诺基亚的MeeGo系统。这些操作系统都曾昙花一现,最终查无此人2021年6。18最值得购买的手机完结喜欢我的文章吗?请点上方蓝色字体关注吧选购指南6。1最值得购买的手机小雷。2021。5。31勘误1红米K40pro,8128G售价2499元实际为2299元2参数表魅族17实际为魅MEIZUWatch正式发布,支持eSIM功能,售价1499元今天下午,魅族智能生活发布会如期举行,此次发布会上,魅族带来了LiproLED智能吸顶灯等数款灯具产品,不过相比之下,最令人关注的无疑是跳票数月,终于正式发布的魅族首款智能手表ME大厂公关嘲讽华为鸿蒙后被离职人心隔肚皮,手机圈也玩无间道?一个O厂小公关的冲动发言,搅得整个互联网都不安生。24日,在鸿蒙预热之际,O厂公关微博发帖,称鸿蒙本质上是基于AOSP开发,相当于安卓的复制,断言没有厂商会傻到把自己的命脉掌握在别华为ampampquot废太子ampampquot李一男,一手好牌打个稀烂,出走华为后锒铛入狱华为科技公司经过几十年的沉淀,如今已经可以代表中国走向世界,虽然近些年来,经历了严峻的考验,导致华为遭受重创,但正所谓瘦死的骆驼比马大,华为依旧位列全球第六,说到华为的成长历史,不