从jdk1.4开始,java提供了一系列改进的输入/输出处理的新功能,这些功能被统称为新IO(New IO,简称NIO),这些类都被放在java.nio包以及子包中,并且对原java.io包中的很多类都以NIO为基础进行了改写,新增了满足NIO的功能。

一、Buffer

与Buffer各种相关的类主要在java.nio包中

从内部结构上看Buffer就像一个数组,它可以保存多个相同类型相同的数据。

Buffer是一个抽象类,最常用的子类是ByteBuffer,可以在底层字节数组上进行get/set操作。对应其他基本数据类型(boolean除外)都有相应的Buffer类:CharBuffer,ShortBuffer,IntBuffer...等.

Buffer中有三个重要概念:

1)容量(capacity):缓冲区的容量(capacity),标识Buffer的最大数据容量,不可为负值,创建后不能改变

2)界限(limit):第一个不应该被读出或者写入的缓冲区位置索引,也就是说位于limit之后的数据既不可以被读,也不可以被写

3)位置(position):用于指明下一个可以被读出或者写入的缓冲区位置索引

@Test
public void bufferTest() {
//创建一个CharBuffer
CharBuffer cbuff = CharBuffer.allocate(8);
System.out.println("cbuff的容量:"+cbuff.capacity());
System.out.println("cbuff的界限:"+cbuff.limit());
System.out.println("cbuff的位置:"+cbuff.position());
//向cbuff中插入字符
cbuff.put('a');
cbuff.put('b');
cbuff.put('c');
System.out.println("cbuff的容量:"+cbuff.capacity());
System.out.println("cbuff的界限:"+cbuff.limit());
System.out.println("cbuff的位置:"+cbuff.position());
//调用flip方法:将limit设置为position所在的位置,并将position设置为0,即为输出数据做好准备
cbuff.flip();
System.out.println("cbuff的容量:"+cbuff.capacity());
System.out.println("cbuff的界限:"+cbuff.limit());
System.out.println("cbuff的位置:"+cbuff.position());
//取出cbuff中的元素
System.out.println(cbuff.get());
System.out.println("cbuff的容量:"+cbuff.capacity());
System.out.println("cbuff的界限:"+cbuff.limit());
System.out.println("cbuff的位置:"+cbuff.position());
//调用clear方法:clear不是清空数据,她将position设置为0,将limit设置为capactity,即为存入数据做好准备
cbuff.clear();
System.out.println("cbuff的容量:"+cbuff.capacity());
System.out.println("cbuff的界限:"+cbuff.limit());
System.out.println("cbuff的位置:"+cbuff.position());
//绝对取数
System.out.println(cbuff.get(2));
//绝对取数后相应的参数,绝对取数后相应的参数是不会变化的。
System.out.println("cbuff的容量:"+cbuff.capacity());
System.out.println("cbuff的界限:"+cbuff.limit());
System.out.println("cbuff的位置:"+cbuff.position()); } 结果:
cbuff的容量:8
cbuff的界限:8
cbuff的位置:0
cbuff的容量:8
cbuff的界限:8
cbuff的位置:3
cbuff的容量:8
cbuff的界限:3
cbuff的位置:0
a
cbuff的容量:8
cbuff的界限:3
cbuff的位置:1
cbuff的容量:8
cbuff的界限:8
cbuff的位置:0
c
cbuff的容量:8
cbuff的界限:8
cbuff的位置:0

二、Channel

Channel类似于传统的流对象,但与传统的流对象有两个主要区别:

1)Channel可以直接将指定文件的部分或者全部直接映射成Buffer

2)程序不能直接访问Channel中的数据,包括读取写入都不行,Channel只能与Buffer进行交互

Channel接口的实现类有DatagramChannel、FileChannel、ServerSocketChannel、SocketChannel....等。主要是按功能来分的,DatagramChannel用于支持UDP网络通信的Channel,ServerSocketChannel、SocketChannel是用于支持TCP网络通信的Channel 等依次类推。

/**
* Channel测试
* 将FileChannel的全部数据一次映射成ByteBuffer的效果
*/
@Test
public void fileChannelTest() {
File f = new File("G://test//eda_src.sql");
try (// 获取FileChannel
FileChannel inChannel = new FileInputStream(f).getChannel();
FileChannel outChannel = new FileOutputStream("G://test//eda_src_bak.sql").getChannel()) {
//MappedByteBuffer是ByteBuffer的子类,它表示Channel将磁盘文件的部分内容或全部内容映射到内存后得到的结果
//通常MappedByteBuffer是由Channel的map方法返回。
MappedByteBuffer mbb = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
//创建UTF-8创建解码器
Charset charset = Charset.forName("UTF-8");
//将buffer的数据全部输出
outChannel.write(mbb);
//将mbb恢复
mbb.clear();
//创建解码器
CharBuffer cbuff = charset.decode(mbb);
System.out.println(cbuff); } catch (Exception e) {
e.printStackTrace();
}
} /**
* Channel测试
* 如果Channel对应的文件过大,一次性映射到内存中引起性能下降,可以采用“竹筒多次重复取水”的方式
* 实现文件复制
*/
@Test
public void fileChannelTest1() {
File f = new File("G://test//eda_src.sql");
try (// 获取FileChannel
FileChannel inChannel = new FileInputStream(f).getChannel();
FileChannel outChannel = new FileOutputStream("G://test//eda_src_bak1.sql").getChannel()) {
//定义一个ByteBuffer对象,用于重复取水
ByteBuffer bbuff = ByteBuffer.allocate(1024); while(inChannel.read(bbuff) != -1) {
//准备读取数据
bbuff.flip();
outChannel.write(bbuff);
//准备写入数据
bbuff.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}

三、字符集和Charset

在计算机里所有的文件,数据等在底层都是二进制文件,即全部是字节码。对于文本文件,之所以看到一个个字符,这是因为系统将底层的二进制序列转换成字符的缘故。在这个过程中涉及到两个概念:编码(Encode)和解码(Decode)

通常而言:

Encode:把明文的字符序列转换成计算机所理解的二进制序列称为编码

Decode:把二进制序列转换成普通人能看懂的明文字符串称为解码

/**
* 编码,解码
* @throws Exception
*/
@Test
public void CharsetTest() throws Exception {
Charset charset = Charset.forName("UTF-8");
CharBuffer cbuff = CharBuffer.allocate(10);
cbuff.put('孙');
cbuff.put('悟');
cbuff.put('空');
cbuff.flip();
ByteBuffer bbuff = charset.newEncoder().encode(cbuff);
cbuff.clear();
//编码
System.out.println(bbuff.get(5));
bbuff.flip();
//解码
System.out.println(charset.newDecoder().decode(bbuff));
}

四、NIO.2

JAVA7对原有的NIO进行了重大改进,改进主要包括如下两方面的内容(java7把这种改进称为NIO.2)

1)提供了全面的文件IO和文件系统访问支持(java7新增了java.nio.file包及各个子包)

2)基于异步Channel的IO(java7在java.nio.channels新增了多个以Asynchronous开头的Channel接口和类)

JAVA传统File类功能比较有限,NIO.2中引入了Path接口和Files、Paths两个工具类来弥补这种不足。

/**
* Paths测试
* @throws Exception
*/
@Test
public void pathTest() throws Exception {
//以当前路径来获取Path对象
Path path = Paths.get(".");
//path路径
System.out.println(path);
//绝对路径
System.out.println(path.toAbsolutePath());
//真实路径
System.out.println(path.toRealPath());
//获取路径名数量
System.out.println(path.getNameCount());
//获取绝对路径名数量
System.out.println(path.toAbsolutePath().getNameCount());
//获取真实路径名数量
System.out.println(path.toRealPath().getNameCount());
} /**
* Files测试
* @throws Exception
*/
@Test
public void filesTest() throws Exception { // 复制文件
Files.copy(Paths.get("G://test//eda_src_bak1.sql"),
new FileOutputStream("G://test//eda_src_bak2.sql"));
//判断文件是否为影藏文件
System.out.println(Files.isHidden(Paths.get("G://test//eda_src_bak2.sql")));
//一次性读取文件所有行
List<String> lines = Files.readAllLines(Paths.get("G://test//eda_src_bak2.sql"));
System.out.println(lines);
//获取文件大小
System.out.println(Files.size(Paths.get("G://test//eda_src_bak2.sql")));
//直接将多个字符串内容写入到指定文件中
List<String> l = new ArrayList<>();
l.add("飞流直下三千尺");
l.add("佛说因果有缘");
Files.write(Paths.get("G://test//eda_src_bak3.sql"), l, Charset.forName("UTF-8"));
//判断C盘总空间,可用空间
FileStore cStore = Files.getFileStore(Paths.get("C:"));
System.out.println("C盘总空间"+cStore.getTotalSpace());
System.out.println("C可用空间"+cStore.getUsableSpace());
} /**
* 使用FileVistor遍历目录
* FileVisitor接口代表一个文件访问器,定义了四个方法
* FileVisitResult visitFile(T file, BasicFileAttributes attrs) 访问文件时触发该方法
* FileVisitResult visitFileFailed(T file, IOException exc) 访问文件失败时触发该方法
* FileVisitResult postVisitDirectory(T dir, IOException exc) 访问子目录之前触发该方法
* FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) 访问子目录之后触发该方法
* 四个方法会返回FileVisitResult对象,这是一个枚举类
* CONTINUE:继续访问
* SKIP_SIBLINGS:继续访问,但不访问该文件或目录的兄弟文件或目录
* SKIP_SUBTREE:继续访问,但不访问该文件或目录的子目录树
* TERMINATE:终止访问
*
* @throws Exception
*/
@Test
public void FileVistorTest() throws Exception {
//遍历G:\test所有文件及子目录
Files.walkFileTree(Paths.get("G://test"), new SimpleFileVisitor<Path>() { @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println(file.toRealPath());
return FileVisitResult.CONTINUE; } });

IO编程之NIO的更多相关文章

  1. 【Java】网络编程之NIO

    简单记录 慕课网-解锁网络编程之NIO的前世今生 & 一站式学习Java网络编程 全面理解BIO/NIO/AIO 内容概览 文章目录 1.[了解] NIO网络编程模型 1.1.NIO简介 1. ...

  2. Netty网络编程之NIO概览与简单应用

    >>关于NIO Java NIO即Java Non-blocking IO(Java非阻塞I/O),是Jdk1.4之后增加的一套操作I/O工具包,又被叫做Java New IO. (1)R ...

  3. 网络编程之NIO

    传统的BIO(Blocking IO)的缺点: 1.基于阻塞式IO建立起来的,导致服务端一直阻塞等待着客户端发起请求,如果客户端不发起,服务端的的业务线程会一直存. 2.弹性伸缩能力差,线程数和客户端 ...

  4. 解锁网络编程之NIO的前世今生

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) NIO 内容概览: NIO 网络编程模型 NIO 网络编程详解 NIO 网络编程实战 NIO 网络编程缺 ...

  5. PHP并发IO编程之路

    并发IO问题一直是服务器端编程中的技术难题,从最早的同步阻塞直接Fork进程,到Worker进程池/线程池,到现在的异步IO.协程.PHP程序员因为有强大的LAMP框架,对这类底层方面的知识知之甚少, ...

  6. Python3 IO编程之StringIO和BytesIO

    StringIO 很多时候,数据读写不一定是文件,也可以在内存中读写. 要把str写入StringIO,我们需要先创建一个StringIO,然后像文件一样写入即可 >>> from ...

  7. IO编程之IO流

    Java的IO流是实现输入.输出的基础,它可以方便的实现数据的输入输出操作.在Java中把不同的输入输出源(键盘.文件.网络连接)抽象表述为流(stream).通过流可以使java程序使用相同的方式访 ...

  8. IO编程之File类

    File类是java.io包下代表与平台无关的文件及目录,程序操作文件和目录都可以通过File类来完成.值得指出的是,不管是文件还是目录都可以通过File类来操作.File能新建.删除.重命名文件和目 ...

  9. IO编程之writelines方法

    1.使用with open as 函数写入文件 2.创建后的文件名为database.txt 3.创建一个函数进行读取文件,使用for循环遍历整个文件内容 4.使用if __name__=='__ma ...

随机推荐

  1. TensorFlow创建DeepDream网络

    TensorFlow创建DeepDream网络 Google 于 2014 年在 ImageNet 大型视觉识别竞赛(ILSVRC)训练了一个神经网络,并于 2015 年 7 月开放源代码. 该网络学 ...

  2. Caffe框架GPU与MLU计算结果不一致请问如何调试?

    Caffe框架GPU与MLU计算结果不一致请问如何调试? 某一检测模型移植到Cambricon Caffe上时,发现无法检测出结果,于是将GPU和MLU的运行结果输出并保存后进行对比,发现二者计算结果 ...

  3. YOLOv4没交棒,但YOLOv5来了!

    YOLOv4没交棒,但YOLOv5来了! 前言 4月24日,YOLOv4来了! 5月30日,"YOLOv5"来了! 这里的 "YOLOv5" 是带有引号的,因为 ...

  4. Java网络编程实践

    网络编程的目的 无线电台......传播交流信息,数据交换.通信 想要达到这个效果需要什么: 1. 如何准确的定位网络上的第一台主机 192.168.16.124:端口,定位到这个计算机上的某个资源. ...

  5. 09:jQuery(02)

    内容概要 jQuery操作标签 jQuery绑定事件 jQuery补充知识点 jQuery动画效果(了解) 零散补充 内容详细 jQuery练习题 $('#i1') r.fn.init [div#i1 ...

  6. 【题解】Luogu p2964 BZOJ 2017[Usaco2009 Nov]硬币游戏

    题目描述 Farmer John's cows like to play coin games so FJ has invented with a new two-player coin game c ...

  7. Java安全之反序列化回显研究

    Java安全之反序列化回显研究 0x00 前言 续上文反序列化回显与内存马,继续来看看反序列化回显的方式.上篇文中其实是利用中间件中存储的Request 和Response对象来进行回显.但并不止这么 ...

  8. 每日三道面试题,通往自由的道路6——JVM

    茫茫人海千千万万,感谢这一秒你看到这里.希望我的面试题系列能对你的有所帮助!共勉! 愿你在未来的日子,保持热爱,奔赴山海! 每日三道面试题,成就更好自我 今天我们继续聊聊JVM的话题吧! 1. 那你知 ...

  9. 堆和栈的内存分布&一些关于内存泄露、栈溢出和野指针的内容(头秃

    内存泄漏&栈溢出 C++中,我们主要涉及的内存是栈和堆, 堆  (By programmer) 申请后由程序员主动释放,遗忘后果严重: 栈 (By compiler)需要时由编译器分配,在不需 ...

  10. 不藏了,这些Java反射用法总结都告诉你们

    摘要:Java反射是一种非常强大的机制,它可以在同一个系统中去检测内部的类的字段.方法和构造函数.它非常多的Java框架中,都大量应用了反射技术,如Hibernate和Spring.可以说,反射机制的 ...