文章目录
- 基本概念
- 一、流式部分
- 1、输入流基类:InputStream 类和 Reader 类
- 2、输出流基类:OutputStream 类和 Writer 类
- 3、处理流
- 转换流
- 推回输入流
- 二、非流式部分
- 1、File 类
- 2、RandomAccessFile 类
- 3、Serializable 接口
基本概念
Java IO 即 Java 的输入/输出系统,其主要包含以下三个部分:
- 流式部分:IO 的主体部分。
- 非流式部分:主要包含一些辅助流式部分的类,如:File 类、SerializablePermission 类、RandomAccessFile 类和 FileDescriptor 等类。
Java IO 中重点掌握五个类(File、OutputStream、InputStream、Writer、Reader)和一个接口(Serializable)。
一、流式部分
Java 的 IO 流式实现输入/输出的基础,可以方便的实现数据的输入和输出操作。按照不同的分类方式,可以将流分为不同的类型:
- 输入流和输出流:根据流的方向来区分,此处的输入和输出都是以程序运行所在的内存的角度来划分的。输入流主要由 InputStream 和 Reader 作为基类;输出流主要由 OutputStream 和 Writer 作为基类。
- 字节流和字符流:根据操作的数据单元不同进行区分,字节流操作的数据单位是 8 位的字节,而字符流操作的数据单位是 16 位的字符。字节流主要由 InputStream 和 OutputStream 作为基类;字符流主要由 Reader 和 Writer 作为基类。
- 节点流和处理流:按照流的角色来划分。节点流直接跟特定的 IO 设备进行交互,程序直接连接到实际的数据源;处理流则用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据的读写功能。
1、输入流基类:InputStream 类和 Reader 类
InputStream 类和 Reader 类是两个抽象基类,本身并不能创建实例来执行输出,但它们是所有输入流的模板。
InputStream 包含的方法如下:
- int read():从输入流中读取单个字节,返回所读取的字节数据(可直接转换为 int 类型)。
- int read(byte[] b):从输入流中最多读取 b.length 个字节的数据到字节数组 b 中,返回实际读取的字节数。
- int read(byte[] b, int off, int len):从输入流中最多读取 b.length 个字节的数据,并将其储存在字节数组 b 中,放入数组 b 中时,不从数组起点开始,而是从 off 位置开始,返回实际读取的字节数。
Reader 包含的方法如下:
- int read():从输入流中读取单个字符,返回所读取的字符数据(可直接转换为 int 类型)。
- int read(char[] cbuf):从输入流中最多读取 cbuf.length 个字符的数据到字符数组 cbuf 中,返回实际读取的字符数。
- int read(char[] cbuf, int off, int len):从输入流中最多读取 cbuf.length 个字符的数据,并将其储存在字符数组 cbuf 中,放入数组 cbuf 中时,不从数组起点开始,而是从 off 位置开始,返回实际读取的字符数。
InputStream 和 Reader 用于移动记录指针的方法如下:
- void mark(int readAheadLimit):在记录指针当前位置记录一个标记。
- boolean markSupported():判断此输入流是否支持 mark() 操作,即是否支持记录标记。
- void reset():将记录指针重新定位到上一次记录标记(mark)的位置。
- long skip(long n):将记录指针向前移动 n 个字节(字符)。
2、输出流基类:OutputStream 类和 Writer 类
OutputStream 类和 Writer 类也是两个抽象基类,本身并不能创建实例来执行输出,但它们是所有输出流的模板。
OutputStream 和 Writer 包含的共同方法如下:
- void write(int c):将指定的字节/字符输出到输出流中,其中 c 可以表示字节,也可以表示字符。
- void write(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定输出流中。
- void write(byte[]/char[] buf, int off, int len):将字节数组/字符数组中从 off 位置开始,长度为 len 的字节/字符输出到指定输出流中。
Writer 包含的额外方法如下:
- void write(String str):将 str 字符串里包含的字符输出到指定输出流中。
- void write(String str, int off, int len):将 str 字符串里从 off 位置开始,长度为 len 的字符输出到指定的输出流中。
OutputStream 包含的额外方法如下:
- void flush() :刷新输出流,强制缓冲区中的输出字节被写出。
- void close() :关闭输出流,释放和这个流相关的系统资源。
3、处理流
处理流是一种典型的装饰器模式,其功能体现在以下两个方面:
- 性能的提高:以增加缓冲的方式来提高读写效率。
- 操作的便捷:提供了一系列便捷的方法来一次读写大批量的内容。
在对输入流/输出流的抽象基类进行适用各种场景的封装之后,输入流/输出流的体系如下:
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
访问字符串 | StringReader | StringWriter | ||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream | ||
抽象基类 | FileInputStream | FileOutputStream | FileReader | FileWriter |
打印流 | PrintStream | PrintWriter | ||
推回输入流 | PushbackInputStream | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
说明:粗体字标注的类代表节点流,斜体字标注的类代表抽象基类。
转换流
转换流用于将字节流转换成字符流,InputStreamReader 将字节输入流转换成字符输入流,OutputStreamWriter 将字节输出流转换成字符输出流。
推回输入流
推回输入流有 PushbackInputStream 和 PushbackReader。推回输入流有一个推回缓冲区,程序可以将制定数组中的内容推回到该缓冲区中,推回输入流读取数据时总是先从推回缓冲区读取,推回缓冲区的内容读取完毕之后才会从原输入流中继续读取。创建推回输入流时需要指定推回缓冲区的大小,默认的推回缓冲区的长度为 1。
PushbackInputStream 和 PushbackReader 都提供的三个方法如下:
- void unread(byte[]/char[] buf):将一个字节(字符)数组内容推回到推回缓冲区里。
- void unread(byte[]/char[] b, int off, int len):将一个字节(字符)数组从 off 开始,长度为 len 字节(字符)的内容推回到推回缓冲区里。
- void unread(int b):将一个字节(字符)推回缓冲区里。
二、非流式部分
1、File 类
用于在程序中操作文件和目录,File 能新建、删除、重命名文件和目录,但不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。File 类可以使用文件路径字符串来创建 File 实例,该路径字符串可以是绝对路径,也可以是相对路径。File 类的常用方法如下:
访问文件名相关的方法:
- String getName():返回此 File 对象所表示的文件名或路径名(如果是路径,则返回最后一级子路径名)。
- String getPath():返回此 File 的路径名。
- File getAbsoluteFile():返回此 File 对象的绝对路径。
- String getAbsolutePath():返回此 File 对象所对应的绝对路径名。
- String getParent():返回此 File 对象所对应目录(最后一级子目录)的父目录名。
- boolean renameTo(File newName):重命名此 File 对象所对应的文件或目录,成功返回 true,失败返回 false。
文件检测相关的方法:
- boolean exists():判断该文件或者目录是否存在。
- boolean canWrite():判断该文件或者目录是否可写。
- boolean canRead():判断该文件或者目录是否可读。
- boolean isFile():判断该对象是否为文件。
- boolean isDirector():判断该对象是否为目录。
- boolean isAbsolute():判断该对象是否为绝对路径。
获取常规文件信息:
- long lastModified():返回文件的最后修改时间。
- long length():返回文件内容的长度。
文件操作相关的方法:
- boolean createNewFile():当此 File 对象所对应的文件不存在时,该方法将新建一个该 File 对象所指定的新文件,创建成功返回 true,否则返回 false。
- boolean delete():删除 File 对象所对应的文件或路径。
- statice File createTempFile(String prefix, String suffix):在默认的临时文件目录中创建一个临时的空文件,使用系统给定的前缀、系统生成的随机数和给定的后缀作为文件名。suffix 参数可为 null,此时将使用默认后缀“.tmp”。
- statice File createTempFile(String prefix, String suffix, File director):在 director 所指定的目录中创建一个临时的空文件,使用系统给定的前缀、系统生成的随机数和给定的后缀作为文件名。
- void deleteOnExit():注册一个删除钩子,指定当虚拟机退出时,删除 File 对象所对应的文件和目录。
目录操作相关的方法:
- boolean mkdir():创建一个 File 对象所对应的目录,成功返回 true,失败返回 false。调用该方法时 File 对象必须对应一个路径,而不是一个文件。
- String[] list():列出 File 对象的所有子文件名和路径名,返回 String 数组。
- File[] listFiles():列出 File 对象的所有子文件和路径,返回 File 数组。
- static File[] listRoots():列出系统的所有根路径。
2、RandomAccessFile 类
RandomAccessFile 是一个特殊的类,既不是输入流也不是输出流,它两者都可以做到。他是 Object 的直接子类。通常来说,一个流只有一个功能,要么读,要么写。但是 RandomAccessFile 既可以读文件,也可以写文件。而且 RandomAccessFile 支持对文件的“随机访问”,程序可以直接跳转到文件的任意地方来读写数据。
RandomAccessFile 中有以下两个方法来操作文件记录指针:
- long getFilePointer():返回文件指针的当前位置。
- void seek(long pos):将文件记录指针定位到 pos 位置。
RandomAccessFile 包含了类似于 InputStream 的三个 read() 方法,也包含了类似于 OutputStream 的三个 write() 方法。
RandomAccessFile 类有两个构造器:
- RandomAccessFile(String str, mode m):即文件名和打开方式。
- RandomAccessFile(File file, mode m):File 参数和打开方式。
mode 参数指定文件的打开方式,有以下四个值:
- “r”:只读。
- “rw”:可读可写。
- “rws”:可读可写,实时更新,刷新文件的内容和文件的修改日期。
- “rwd”:可读可写,实时更新,刷新文件的内容,但修改日期可能不会更改,直到文件关闭。
3、Serializable 接口
对象序列化是指将 Java 对象写入 IO 流中,使之可以保存在磁盘上,或者通过网络传输。通过反序列化可以从 IO 流中恢复该 Java 对象。
实现 Serializable 接口可以实现对象序列化,该接口中没有需要实现的方法,只是为了标注该对象是可被序列化的。