File类

File是文件或者文件夹的抽象,File代表的仅仅是一个路径而已

新建

  • createNewFile():创建文件
  • mkdir():创建目录,如果新目录的前面的路径不存在,则不创建
  • mkdirs():创建多级目录,不管新目录的前面的路径不存在,都会创建

判断

  • isDirectory():是否是目录
  • isFile:是否是文件
  • exitsts():是否存在
  • getAbsolutePath():获取绝对路径
  • getPath():获取相对路径
  • getName():获取名字
  • list():列出所有的文件或者目录的名字
  • listFiles():列出所有的文件或者目录的路径

用记事本打开能看懂就用字符流,看不懂就用字节流

字节流

image-20240509142429921

字节输出流OutputStream

FileOutputStream

FileOutputStream默认是覆盖写入,需要使用其它构造器来实现追加写入

String.getBytes():获取一个字节数组

  • write(int num):写一个字节
  • write(byte[] bytes):写一个字节数组
  • write(byte[] bytes, int off, int len):从off位置写长度为len字节的一个字节数组

字节输入流InputStream

FileInputStream

用数组读取,new String(byte[] bytes, 0, len)就可以打印输出

  • int read(int num):读取一个字节,返回读取到的下一个字节数据
  • int read(byte[] bytes):读取一个字节数组,返回读取到的字节长度
  • int read(byte[] bytes, int off, int len):从off位置读取长度为len字节的一个字节数组,返回读取到的字节长度

字节缓冲流Buffer

先创建一个缓冲区,默认值2^14=8192,当然也可以自己指定,在读取或者写数据的时候,减少系统调用的次数

字节缓冲输出流BufferOutputStream

字节缓冲输入流BufferInputStream

字符流

中文根据不同的编码用不同长度的字节存储,如GBK是2个字节、UTF-8是3个字节

字符流 = 字节流 + 编码表

字符流是有缓冲的,需要调用flush()刷新

image-20240509142613420

编码解码问题

image-20240508151153318

字符输出流OutputStreamWriter

为了编写代码方便,可以改用FileWriter

  • write(int num):写一个字符
  • write(char[] cbuf):写一个字符数组
  • write(char[] cbuf, int off, int len):写字符数组的一部分
  • write(String str):写一个字符串
  • write(String str, int off, int len):写字符串的一部分

字符输入流InputStreamReader

为了编写代码方便,可以改用FileReader

用数组读取,new String(char[] cbuf, 0, len)就可以打印输出

  • int read(int num):读取一个字符,返回读取到下一个字符数据
  • int read(char[] cbuf):读取一个字符数组,返回读取到的字节长度

字符缓冲流Buffer

类似字节缓冲流

字节缓冲输出流BufferedWriter

newLine():根据操作系统不同写换行符,如windows是\r\n,linux是\n

字节缓冲输入流BufferedReader

String readLine():读取一行数据,不包括换行符,直到结尾返回null

异常处理

image-20240509144527146

特殊操作流

标准输入输出流

InputStream is = System.in,是一个字节输入流,如果需要读取字符,需要用转换流(InputStreamReader)包装

PrintStream ps = System.out,是一个字节输出流

打印流

类似于另一种缓冲流

字节打印流PrintStream

  • write():同字节输出流
  • print():直接打印括号内的东西

字符打印流PrintWriter

根据构造器不同,决定println()会不会自动刷新缓冲区,或者自己手动调用flush()

对象序列化流

对象序列化流ObjectOutPutStream

writeObject(Object obj):序列化对象成一个字节流存储或者网络传输,人类看不懂

对象反序列化流ObjectInPutStream

readObject():反序列化对象

序列化详解

序列化会给类产生一个序列化ID serialVersionUID,如果对类进行修改,序列化ID就会不同,会报错,建议自己定义一个serialVersionUID成员变量

Properties类

Properties是Map的子类,可以与流配合使用

  • load(InputStream is):
  • load(Reader r):
  • store(OutputStream os):
  • store(Writer w):

IO分类

  • 工作层面:本地磁盘IO、网络IO
  • 工作性质:阻塞IO、非阻塞IO
  • 工作线程:同步IO、异步IO
  • 工作模式:BIO、NIO、AIO

Linux的五种IO模型

数据的获取分三阶段执行:

  • 数据准备:将数据从磁盘或者网卡读取到内核缓存区
  • CPU中断:调用内核中断程序,通知CPU数据准备完成
  • 数据复制:将数据从内核缓存区读取到程序缓存区

BIO同步阻塞模型

数据准备和复制阶段CPU都需要阻塞等待

NIO同步非阻塞模型

数据准备和复制阶段CPU不需要阻塞等待,但是要不断轮询

多路复用模型

解决NIO不断轮询导致的CPU占用过高,以及避免服务端线程和用户线程1:1的过多连接

主要有select/poll/epoll三种实现方式

信号驱动模型

先在内核注册一个信号处理函数,数据准备是异步非阻塞的;

数据准备到内核缓冲区后,内核会向进程发送信号,之后的数据复制阶段是同步阻塞的

AIO异步非阻塞模型

数据准备与复制阶段都是异步非阻塞