1:File 类

java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
构造

  • public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File 实例。
  • public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File 实例。
  • public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File 实例。

获取

  • public String getAbsolutePath() :返回此 File 的绝对路径名字符串。
  • public String getPath() :将此 File 转换为路径名字符串。
  • public String getName() :返回由此 File 表示的文件或目录的名称。
  • public long length() :返回由此 File 表示的文件的长度。

判断

  • public boolean exists() :此 File 表示的文件或目录是否实际存在。
  • public boolean isDirectory() :此 File 表示的是否为目录。
  • public boolean isFile() :此 File 表示的是否为文件。

创建删除功能的方法

  • public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
  • public boolean delete() :删除由此 File 表示的文件或目录。
  • public boolean mkdir() :创建由此 File 表示的目录。
  • public boolean mkdirs() :创建由此 File 表示的目录,包括任何必需但不存在的父目录。
  • public Boolean renameTo(File dest)把文件 重命名为指定的路

    2:IO 流原理及流的分类

    按操作数据单位不同分为:字节流(8bit),字符流(16bit)
    按数据流的流向不同分为:输入流,输出流
    按流的角色不同分为:节点流(直接从数据源或目的地读写数据),处理流(连接在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能)
    六、IO 与 NIO - 图1

六、IO 与 NIO - 图2

字节流与字符流的区别:
1:字节流操作文件不会用到缓存,直接操作文件,儿字符流是先写到缓存再写到问价

字节流:

字节(Byte):八位 0-255
一切皆字节
1:字节输出流 OutputStream
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b) :将 b.length 字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len 字节,从偏移量 off 开始输出到此输出流。
public abstract void write(int b) :将指定的字节输出流。
文件输出流 FileOutputStream
public FileOutputStream(File file) :创建文件输出流以写入由指定的 File 对象表示的文件。 public FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件。
public FileOutputStream(File file, boolean append) : 创建文件输出流以写入由指定的 File 对象表示的文件。
public FileOutputStream(String name, boolean append) : 创建文件输出流以指定的名称写入文件。

字符流

字符:字的符号
①ASCII 码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为 8 位二进制数,换算为十进制。最小值 0,最大值 255。
②UTF-8 编码中,一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
③Unicode 编码中,一个英文等于两个字节,一个中文(含繁体)等于两个字节。
符号:英文标点占一个字节,中文标点占两个字节。举例:英文句号“.”占 1 个字节的大小,中文句号“。”占 2 个字节的大小。
④UTF-16 编码中,一个英文字母字符或一个汉字字符存储都需要 2 个字节(Unicode 扩展区的一些汉字存储需要 4 个字节)。
⑤UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。
六、IO 与 NIO - 图3

3:节点流(文件流)

读取文件

  1. 建立一个流对象,将已存在的文件加载进流

FileReader = new new new FileReader(new File(“Test.txt”));

  1. 创建一个临时存放数据的组。

 char[] ch = new char[1024];

  1. 调用流对象的读取方法将中数据入到组。

fr.read (ch );

  1. 关闭资源。

 fr.close();
写入文件
1:创建流对象,建立数据存放文件
FileWriter fw = new FileWriter(new File(“Test.txt”));
2:调用流对象的写入方法,将数据写入流
Fw.write(“adasdnjakndj”);
3:关闭流资源,并将六种的数据清空到文件中
Fw.close();

4:缓冲流

为了提高数据读写速度,提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数据,默认 8192 字节(8Kb)的缓冲区
六、IO 与 NIO - 图4

缓冲流要套接在相应的节点流之上,
六、IO 与 NIO - 图5

当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
当使用 BufferedInputStream 读取字节文件时,BufferedInputStream 会一次性从文件中读取 8192 个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个 8192 个字节数组。
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,BufferedOutputStream 才会把缓冲区中的数据一次性写到文件里。使用方法 flush()可以强制将缓冲区的内容全部写入输出流
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
flush()方法的使用:手动将 buffer 中内容写入文件
如果是带缓冲区的流对象的 close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出

5:转换流

提供字节流和字符流之间的转换
六、IO 与 NIO - 图6

InputStreamReader:字节输入流按指定字符集转换为字符的输入流
OutputStreamWriter:将字符的输出流按指定字符集转换成字节的输出流

6:标准输入输出流

System.in 和 System.out 分别代表了系统标准的输入和输出设备
System.in 的类型是 InputStream
System.out 的类型是 PrintStream,其是 OutputStream 的子类 FilterOutputStream 的子类

7:打印流

将基本数据类型的数据格式转换为字符串输出
打印流:PrintStreamPrintWriter
PrintStream 和 PrintWriter 的输出不会抛出 IOException 异常

8:数据流

方便操作 Java 语言的基本数据类型和 String 的数据,使用数据流,用于读取和写出基本数据类型,String 类的数据
DataInputStream 和 DataOutputStream,分别套接在 InputStream 和 OutputStream 子类的流上。
六、IO 与 NIO - 图7

9:对象流

ObjectInputStream 和 OjbectOutputSteam
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把 Java 中的对象写入到数据源中,也能把对象从数据源中还原回来。
序列化:用 ObjectOutputStream 类保存基本类型数据或对象的机制
反序列化:用 ObjectInputStream 类读取基本类型数据或对象的机制
ObjectOutputStream 和 ObjectInputStream 不能序列化 static 和 transient 修饰的成员变量

10:随机存取文件流

RandomAccessFile 类
RandomAccessFile 声明在 java.io 包下,但直接继承于 java.lang.Object 类。并且它实现了 DataInput、DataOutput 这两个接口,也就意味着这个类既可以读也可以写。
RandomAccessFile 类支持“随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
 支持只访问文件的部分内容
 可以向已存在的文件后追加内容
RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile 类对象可以自由移动记录指针:
long getFilePointer():获取文件记录指针的当前位置
void seek(long pos):将文件记录指针定位到 pos 位置

11:BIO

Block IO:jdk 最早抽象出的 IO 体系,jdk1.0 的 io 体系是阻塞的。
六、IO 与 NIO - 图8

流程:
当调用 java BIO 的 write()方法写数据时,实际上调用的是底层 socket。写到 socket 的写缓冲区(write buffer)。(注意当调用 write()方法返回时,不代表数据已经发送出去,此时仅仅写入了 socket 的 write buffer 而已)。操作系统有一个专门的线程用于检查写缓冲区,有数据后将数据送入网卡设备经网络传送出去。
同理,对于读缓存区也一样。当调用系统的 read()方法时,是从 socket 的读缓冲区读数据。(系统内核有线程会将收到的数据拷贝到 socket 读缓冲区供用户空间使用)
两个缓冲区的大小是有限的,当写缓冲区写满后,会阻塞写操作,当读缓冲区为空后,会阻塞读操作。这是阻塞的根源。

11:NIO

Java NIO (New IO,Non-Blocking IO)是从 Java 1.4 版本开始引入的一套新的 IO API,可以替代标准的 Java IO API。NIO 与原来的 IO 有同样的作用和目的,但是使用的方式完全不同,NIO 支持面向缓冲区的(IO 是面向流的)、基于通道的 IO 操作。NIO 将以更加高效的方式进行文件的读写操作。
Java API 中提供了两套 NIO,一套是针对标准输入输出 NIO,另一套就是网络编程 NIO。
|——-java.nio.channels.Channel
|——-FileChannel:处理本地文件
|——-SocketChannel:TCP 网络编程的客户端的 Channel
|——-ServerSocketChannel:TCP 网络编程的服务器端的 Channel
|——-DatagramChannel:UDP 网络编程中发送端和接收端的 Channel
Path、Paths 和 Files 核心 API
早期的 Java 只提供了一个 File 类来访问文件系统,但 File 类的功能比较有限,所提供的方法性能也不高。而且,大多数方法在出错时仅返回失败,并不会提供异常信息。
NIO.2 为了弥补这种不足,引入了 Path 接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path 可以看成是 File 类的升级版本,实际引用的资源也可以不存在。
在以前 IO 操作都是这样写的:
import java.io.File;
File file = new File(“index.html”);
但在 Java7 中,我们可以这样写:
import java.nio.file.Path;

import java.nio.file.Paths;

Path path = Paths.get(“index.html”);
六、IO 与 NIO - 图9

六、IO 与 NIO - 图10

流的一层层封装,装饰者模式
区别:IO 是面向流的,NIO 是面向缓冲区的
三大核心部分:Channel(通道),Buffer(缓冲区), Selector。
传统 IO 基于字节流和字符流进行操作,而 NIO 基于 Channel 和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。

1:Channel

与 BIO 中的 stream 差不多,只不过 stream 是单向的,而通道 channel 是双向的,其主要实现有:
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel

2:Buffer

一个 Buffer 对象是固定数量的数据的容器,其作用是一个存储器,或者分段运输区,在这里,数据可被存储并在之后用于检索。缓冲区可以被写满或释放。对于每个非布尔原始数据类型都有一个缓冲区类,即 Buffer 的子类有:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer 和 ShortBuffer,是没有 BooleanBuffer 之说的。尽管缓冲区作用于它们存储的原始数据类型,但缓冲区十分倾向于处理字节。非字节缓冲区可以在后台执行从字节或到字节的转换,这取决于缓冲区是如何创建的。
缓冲区的四个属性:

  • 容量 Capactity:缓冲区能够容纳的数据元素的最大容量。
  • 上界 limit:缓冲区的第一个不能被读或写的元素,缓冲创建时,limit 的值等于 capacity 的值,假设 capacity = 1024,我们在程序中设置了 limit = 512,说明,Buffer 的容量为 1024,但是从 512 之后既不能读也不能写,因此可以理解成,Buffer 的实际可用大小为 512。
  • 位置 Position:下一个要被读或写的元素的索引,位置会自动由相应的 get()和 put()函数更新。position 的位置是从 0 开始的。
  • 标记 Mark:一个备忘位置,标记在设定前是未定义的。使用场景是,假设缓冲区中有 10 个元素,position 目前的位置为 2(也就是如果 get 的话是第三个元素),现在只想发送 6 - 10 之间的缓冲数据,此时我们可以 buffer.mark(buffer.position()),即把当前的 position 记入 mark 中,然后 buffer.postion(6),此时发送给 channel 的数据就是 6 - 10 的数据。发送完后,我们可以调用 buffer.reset() 使得 position = mark,因此这里的 mark 只是用于临时记录一下位置用的。

    3:selector

    4:鲁班教学
    服务器端:
    六、IO 与 NIO - 图11

客户端:
六、IO 与 NIO - 图12

BIO 的特点,阻塞
在不考虑多线程情况下,BIO 无法处理并发
当一个阻塞时,其他客户端无法再连接到服务器了
可以开线程,每个添加一个线程,但是每来一个线程添加一个线程,耗费大,就像淘宝双 11,但是有很多连接是不买东西的,qq 很多连接不发消息,
设置不阻塞
六、IO 与 NIO - 图13

设置为非阻塞:如果没人连接,打印,看已经连接的有没有发送
六、IO 与 NIO - 图14

如果有人连接,放入 list,遍历 list 看他有没有发送数据
NIO 设置非阻塞:
ServerSocket 变成 ServerSocketChannel
Socket 变成 SocketChannel
六、IO 与 NIO - 图15

13:AIO

Asynchronous IO:异步的,也称 nio2。
BIO 中若某些操作没准备好,则直接阻塞进程,直到完成;NIO 若没操作好,则会监视操作并当操作准备好后通知处理者处理。而 AIO 则是没处理好,去处理别的任务,将其异步通知回调或写入 Future。

对比

1:Java 对 BIO、NIO、AIO 的支持:
Java BIO (blocking I/O):同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
缺点:一个连接占用一个线程资源,线程资源得不到充分利用。线程开销大,利用率不高。
优点:
Java NIO (non-blocking I/O):同步非阻塞,Client 发送一个请求,会被 Server 端放入到多路复用器上,多路复用器轮询这些请求事件,发现 IO 请求,才会启动一个线程去处理。
优点:多路复用,并发性高;
缺点:
IO(NIO.2) (Asynchronous I/O) :异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的 I/O 请求都是由 OS 先完成了再通知服务器应用去启动线程进行处理。但是其实现较为复杂,还有一个 Selector 空轮询的 bug,可能会导致 CPU 占用 100%,他是使用了 Future 来实现即时返回。
每个进程干自己的事情,如果 A 进程发现 B 进程想从我这里获取资源,那 A 进程在使用玩这部分资源后主动通知 B,可以来我这取了,这就不用事件池、也不用耗费资源去做监控。
优点:并发性高,CPU 利用率高,线程利用率高
缺点:进程间频繁的通信在追错,管理和资源消耗上不是很客观。
2:BIO、NIO、AIO 适用场景分析:
BIO 方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 以前的唯一选择,但程序直观简单易理解。
NIO 方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4 开始支持。
AIO 方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用 OS 参与并发操作,编程比较复杂,JDK7 开始支持。
BIO:磁盘->内核空间缓冲区->用户空间缓冲区
NIO:磁盘->用户空间缓冲区
IO 是面向流的,NIO 是面向缓冲区的

转载 https://www.yuque.com/jykss/jykss/zezf4y#WDe4S