java核心学习(十八) javaNIO框架---“块”模型的IO

一、java新IO概述

  javaIO中的输入流和输出流都是通过字节的移动来处理的,面向流的输入输出系统一次只能处理一个字节,因此效率不高,而且传统的输入输出流是阻塞试的,也就是说当无法读到数据时,当前线程会被阻塞直到读取到有效数据才会继续运行。

  java1.4之后提供了一系列改进的输入输出类与方法,并且以NIO为基础改写了java.io包中的类,新增了满足NIO的功能。

  NIO采用内存映射文件的方式,java.nio中主要的包有:

    java.nio ,主要包含于Buffer相关的类;

    java.nio.charset,主要包含字符集相关的类;

    java.nio.channels,主要包含Channel和Selector相关的类;

    java.nio.channels.spi,主要包含与Channel相关的服务提供者编程接口;

    java.nio.charset.spi,包含与字符集相关的服务提供者编程接口。

二、Buffer抽象类

  其子类有ByteBuffer(最常用)、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer,这些类没有构造器,获取buffer对象使用如下静态方法:static XxxBuffer allocate(int capacity)。

  Buffer的几个位置属性:

  

  相应的两个方法:clear(),let limit = capacity and position = 0,这相当于是为再次将数据写入Buffer做好准备,

          flip(),let limit = position and position = 0 ,这相当于是为从Buffer中取出数据做好准备。

package NIOTest;

import java.nio.CharBuffer;

public class BufferTest {
    public static void main(String[] args)
    {
        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("加入三个元素后,position = " + buffer.position());
        buffer.flip();
        System.out.println("执行flip()后,limit = " + buffer.limit());
        System.out.println("position = " + buffer.position());
        //去除第一个元素
        System.out.println("第一个元素(position=0):" + buffer.get());
        System.out.println("取出第一个元素后,position = " + buffer.position());
        //调用clear方法
        buffer.clear();
        System.out.println("执行clear()后,limit = " + buffer.limit());
        System.out.println("执行clear()后,position = " + buffer.position());
        System.out.println("执行clear()后,buffer内容并没有被清除:" + "第三个元素为:"+ buffer.get(2));
        System.out.println("执行绝对读取后,position = " + buffer.position());
    }
}

  上面代码尝试了一下Buffer的使用,输出为下

capacity:8
limit:8
position0
加入三个元素后,position = 3
执行flip()后,limit = 3
position = 0
第一个元素(position=0):a
取出第一个元素后,position = 1
执行clear()后,limit = 8
执行clear()后,position = 0
执行clear()后,buffer内容并没有被清除:第三个元素为:c
执行绝对读取后,position = 0

  上面程序使用的buffer是heapbuffer,每个heapbuffer在新建时都会创建一个对应的directbuffer,直接buffer的读取效率高但是创建成本也高,具体buffer1的工作方式不在这里深究= =,因为深究了没有实际应用也会忘记。。

三、 Channel接口

  Channel用于与Buffer交互,实现数据的IO。

  java为Channel接口提供了DatagramChannel(支持UDP网络通信)、FileChannel(文件读写)、Pipe.SinkChannel和Pipe.SourceChannel(支持线程间通信的管道)、SelectableChannel(可选择阻塞与非阻塞的channel)、ServerSocketChannel和SocketChannel(支持TCP网络通信)等等。

  Channel通过传统的流节点来返回对应的Channel,常用的方法有map()、read()、write(),下面来试一试

  

package NIOTest;

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 FileChannelTest {
    public static void main(String[] args) {
        File f = new File("./src/main/java/NIOTest/FileChannelTest.java");
        try (
                FileChannel inChannnel = new FileInputStream(f).getChannel();
                FileChannel outChannel = new FileOutputStream("a.txt").getChannel();

        ) {
            MappedByteBuffer buffer = inChannnel.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();
        }
    }
}

  下面代码每次运行都会讲a.txt文件的内容复制一份并将全部内容追加到该文件的后面

package NIOTest;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class RandomFileChannelTest {
    public static  void mian (String[] args){
        File f= new File("a.txt");
        try(
                RandomAccessFile raf = new RandomAccessFile(f,"rw");
                FileChannel randomChannel = raf.getChannel();
                ){
            ByteBuffer buffer = randomChannel.map(FileChannel.MapMode.READ_ONLY,0,f.length());       //这里移动的是channel的position,可以在任意位置将数据写入channel。
            randomChannel.position(f.length());
            randomChannel.write(buffer);
        }catch (IOException ioe){
                    ioe.printStackTrace();
        }
    }
}

四、Charset类

  字符集类主要用于文本格式数据编码与解码,具体用法在 三 中的第一个例子有所展示。

时间: 2024-10-27 11:29:42

java核心学习(十八) javaNIO框架---“块”模型的IO的相关文章

java核心学习(十九) javaNIO框架---文件锁

在上一节提到的FileChannel中提供了lock()/tryLock()方法可以获得文件锁FileLock对象,从而锁定文件,这里的文件锁是进程级别的锁,而非线程锁. lock()方法是阻塞试的,当调用该方法且无法得到文件锁,程序将一直阻塞. tryLock()方法是非阻塞式的加锁方法,如果获得了文件锁,则该方法返回该文件锁,否则将返回null. 文件锁分为共享锁和排他锁,当lock/tryLock方法的第三个参数为true时表明该锁是共享锁,共享锁允许多个进城来读取该文件,但阻止其他进程获

Java Web总结十八文件的上传和下载

一.实现Web开发中的文件上传功能,需完成如下两步操作: 1.在web页面中添加上传输入项. 2.在Servlet中读取上传文件的数据,并保存到本地硬盘中. 二.如何在web页面中添加上传输入项? 1.<input type="file">标签用于在web页面中添加文件上传输入项,设置文件上传输入项时须注意: 1)必须设置input输入项的name属性,否则浏览器将不会发送上传文件的数据. 2)必须把form的enctype属性值设为multipart/form-data.

深度学习十大顶级框架

2015 年结束了,是时候看看 2016 年的技术趋势,尤其是关于深度学习方面.新智元在 2015 年底发过一篇文章<深度学习会让机器学习工程师失业吗?>,引起很大的反响.的确,过去一年的时间里,深度学习正在改变越来越多的人工智能领域.Google DeepMind 工程师 Jack Rae 预测说,过去被视为对于中型到大型数据集来说最佳的预测算法的那些模型(比如说提升决策树(Boosted Decision Trees)和随机森林)将会变得无人问津. 深度学习,或者更宽泛地说——使用联结主义

201771010129 王颖奇《面向对象程序设计Java》第十八周实验总结

实验十八  总复习 实验时间 2018-12-30 1.实验目的与要求 (1) 综合掌握java基本程序结构: (2) 综合掌握java面向对象程序设计特点: (3) 综合掌握java GUI 程序设计结构: (4) 综合掌握java多线程编程模型: (5) 综合编程练习. 2.实验内容和步骤 任务1:填写课程课后调查问卷,网址:https://www.wjx.cn/jq/33108969.aspx. 任务2:综合编程练习 练习1:设计一个用户信息采集程序,要求如下: (1) 用户信息输入界面如

java核心学习笔记(一) javaJDK目录阐述

本系列博客为原创博客,旨在学习整理之用,转载请注明出处,谢谢. java作为最成功的语言之一,有很多地方可以学习,不仅仅是语言的用法. 本次学习目标在于系统的从javaSE学起,学习java的理念思想,以及从代码层次直接学习javaSE和他的用法,以此来为将来学习java类库的编写.java开发框架以及javaEE.java虚拟机.javaWEB打下良好的基础,努力让编程成为一种思想,成为身体的一部分. 这次从头重新对java的学习,目的是要学习java的世界观和方法论,学习过程要符合哲学理论,

Java编程思想(十八) —— 再谈反射

在Java编程思想(十五) -- 类型信息之反射和Java编程思想(十六) -- 联系JVM再谈Class,书上只用了3页就讲完了,还有讲了那么多Class的东西,接下来要从反射中怎么用,自己结合API和其他资料再写多一些. 示例:Test.java public class Test { public Test() {     }      public Test(int i) {         System.out.println(i);     } private void pri()

深度学习(八):生成模型

一.引入 最开始知道生成模型和判别模型,是在李航的统计学习方法里,当时的理解是:生成模型,就是同时考虑了X和Y的随机性,也就是说二者都是随机变量:判别模型,就是只考虑了Y的随机性,而X并不是个随机变量,即使X存在于条件中,但是并没有p(x)这种说法.当时同时也知道了,朴素贝叶斯和隐马尔可夫都是生成模型,最主要的原因就是在这两个模型中涉及到的变量都是随机变量.生成模型可以转变成判别模型,也就是生成模型由于考虑的都是随机变量,可以通过条件概率公式计算出条件概率:反之不行,因为判别模型无法描述联合概率

Java多线程学习(八)线程池与Executor 框架

Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide 历史优质文章推荐: Java并发编程指南专栏 分布式系统的经典基础理论 可能是最漂亮的Spring事务管理详解 面试中关于Java虚拟机(jvm)的问题看这篇就够了 目录: [TOC] 本节思维导图: 思维导图源文件+思维导图软件关注微信公众号:"Java面试通关手册" 回复关键字:"Java多线程"

java核心学习(四十) 使用反射生成JDK动态代理

java.lang.reflect包下提供了一个Proxy类和InvocationHandler接口,用于生成动态代理类和动态代理对象. 一.使用Proxy.InvocationHandler创建动态代理 这里要注意,在java.net包下也有一个Proxy类,不过这个类是用于设置代理服务器的,莫混淆.. Proxy提供了如下两个方法创建动态代理类和动态代理实例: 实际上即使采用第一种方法创建动态代理类,如果程序需要通过该代理类来创建对象,依然需要传入一个InvocationHandler对象,