Java-IO流
IO 流的概念
- IO 就是 Input 和 Output 的简写,也就是输入和输出的含义。
- IO 流就是指读写数据时像流水一样从一端流到另外-端,因此得名为"流"。
基本分类
- 按照读写数据的基本单位不同,分为字节流和字符流
- 其中字节流主要指以字节为单位进行数据读写的流,可以读写任意类型的文件。
- 其中字符流主要指以字符(2个字节)为单位进行数据读写的流,只能读写文本文件。
- 按照读写数据的方向不同,分为输入流和输出流(站在程序的角度)。
- 其中输入流主要指从文件中读取数据内容输入到程序中,也就是读文件。
- 其中输出流主要指将程序中的数据内容输出到文件中,也就是写文件。
- 按照流的角色不同分为节点流和处理流。
- 其中节点流主要指直接和输入输出源对接的流。
- 其中处理流主要指需要建立在节点流的基础之上的流。
体系结构
FileWriter 字符输出流
基本概念
java.io.Filewriter类主要用于将本内容写入到文本文件
常用的方法
方法声明 | 功能介绍 |
---|---|
FileWriter(String fileName) | 根据参数指定的文件名构造对象 |
FileWriter(String fileName, boolean append) | 以追加的方式根据参数指定的文件名来构造对象 |
void write(int c) | 写入单个字符 |
void write(char[] cbuf, int off, int len) | 将指定字符数组中从偏移量o开始的en个字符写入此文件输 |
void write(char[] cbuf) | 将 cbuf.length个字符从指定字符数组写入此文件输出流中 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
public static void main(String[] args) {
FileWriter fileWriter = null;
try {
// 构造 FileWriter 对象与 ./a.txt 文件关联
// 若文件不存在该流会自创建新的空文件
// 若文件存在则会清空原有内容
fileWriter = new FileWriter("./a.txt");
// 参数二为true时为追加内容
// fileWriter = new FileWriter("./a.txt",true);
// 通过数据流写入数据内容
fileWriter.write("CONTENT TEXT; ");
char[] arr = {'h', 'e', 'l', 'l', 'o'};
// 将数组一部分内容写入
fileWriter.write(arr, 1, 3); // ell
// 将一组字符写入
fileWriter.write(arr);
// 刷新流 在多次写入且不关闭流的时候时才需要用到
fileWriter.flush();
System.out.println("SUCCESS");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流对象并释放相关内容
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileReader 字符输入流
基本概念
- java.io.FileReader 类主要用于从本文件读取文本数据内容。
常用的方法
方法声明 | 功能介绍 |
---|---|
FileReader(String fileName) | 根据参数指定的文件名构造对象 |
int read() | 读取单个字符的数据并返回,返回 -1 表示读取到末尾 |
int read(char[] cbuf, int offset, int lenght) | 从输入流中将最多lenght个字符的数据读入一个字符数组中,返回读取到的字符个数,返回 -1 表示读取到末尾 |
int read(char[] cbuf) | 从此输入流中将最多 cbuf.length 个字符的数据读入字符数组中,返回读取到的字符个数,返回 -1 表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
- reader() 读取文件全部内容
public static void main(String[] args) {
FileReader fileReader = null;
try {
// 1.构造 FileReader 类型的对句d:/a.txt文件关
fileReader = new FileReader("./a.txt");
// 2.读取数据内容并打印
// int read = fileReader.read(); 读取一个字符
// System.out.println((char)read);
// 读取文件中所有内容
int read;
while ((read = fileReader.read()) != -1) {
System.out.print((char) read);
}
} catch (IOException e) {
// 3.关闭流对并释放有关的资源
if (null != fileReader) {
try {
fileReader.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
}
}
- reader() 其他版本的使用
public static void main(String[] args) {
FileReader fileReader = null;
try {
// 1.构造 FileReader 对象关联 ./a.txt 文件
fileReader = new FileReader("./a.txt");
// 2.期望读满字符数字部分空间
char[] strArr = new char[5];
// fileReader.read(strArr, 1, 3);
// System.out.println(strArr);
// 期望读满字符数组所有空间
int read = fileReader.read(strArr);
System.out.println(strArr);
} catch (IOException e) {
// 3.关闭流对并释放有关的资源
if (null != fileReader) {
try {
fileReader.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
}
}
FileOutputstream 字节输出流
基本概念
java.io.FileOutputStrean
类主要用于将图像数据之类的原始字节流写入到输出流中。
常用的方法
方法声明 | 功能介绍 |
---|---|
FileOutputStrean(String fileName) | 根据参数指定的文件名构造对象 |
FileOutputStrean(String fileName, boolean append) | 以追加的方式根据参数指定的文件名来构造对象 |
void write(int c) | 写入单个字符 |
void write(byte[] cbuf, int off, int len) | 将指定字节数组中从偏移量o开始的len个字符写入此文件输 |
void write(byte[] cbuf) | 将 cbuf.length个字符从指定字节数组写入此文件输出流中 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
FileInputStream 字节输入流
基本概念
java.io.FileInputStream
类主要用于从输入流中以字节流的方式读取图像数据等
常用的方法
方法声明 | 功能介绍 |
---|---|
FileReader(String fileName) | 根据参数指定的文件名构造对象 |
int read() | 读取单个字节的数据并返回,返回 -1 表示读取到末尾 |
int read(byte[] cbuf, int offset, int lenght) | 从输入流中将最多lenght个字节的数据读入一个字节数组中,返回读取到的字节个数,返回 -1 表示读取到末尾 |
int read(byte[] cbuf) | 从此输入流中将最多 cbuf.length 个字节的数据读入字符数组中,返回读取到的字符个数,返回 -1 表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
int | available() |
字节流实现图片的拷贝
推荐使用Java官方提供的 缓冲输入输出流
方式一:以单个字节为单位进行拷贝 (不推荐)
每次读取一个字节后在写入一个字节
不能使用这种方式,拷贝的效率很低
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 创建FileInputStream对象与 a.txt 关联
fis = new FileInputStream("./111.jpg");
// 创建FileOutputStream对象与 a.txt 关联
fos = new FileOutputStream("./222.jpg");
System.out.println("正在玩命拷贝中...");
int read;
// 不断的从字节输出流中读取并写入字节输入将中
while ((read = fis.read()) != -1) {
fos.write(read);
}
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭流 释放资源
// 先创建的后关闭 后创建的先关闭
if (null != fos) {
fos.close();
}
if (null != fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
方式二:使用和文件大小一致的缓冲区(不推荐)
准备一个和文件大小一样的线冲区性将文件中的所有内容取出到线冲区然后一次性写入进去。
- 缺点:若文件过大时,无法中请和文件大小一样的线冲区,真实物理内存不足
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 创建FileInputStream对象与 a.txt 关联
fis = new FileInputStream("./111.jpg");
// 创建FileOutputStream对象与 a.txt 关联
fos = new FileOutputStream("./222.jpg");
System.out.println("正在玩命拷贝中...");
// 获取到的文件大小(字节)
int size = fis.available();
System.out.println("获取到的文件大小是:" + size);
// byte数组缓冲区 缓冲区大小为输入流大小
byte[] buffer = new byte[size];
// 将字节流一次性读取到byte缓冲区中
int read = fis.read(buffer);
System.out.println("读取到文件的大小是:" + read);
// 将缓冲区中的字节流一次行写如到输出流中
fos.write(buffer);
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭流 释放资源
// 先创建的后关闭 后创建的先关闭
if (null != fos) {
fos.close();
}
if (null != fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
方式三:相对的缓冲取,多次完成
准备一个相对适当的缓冲区,分多次将文件老贝完成
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 创建FileInputStream对象与 a.txt 关联
fis = new FileInputStream("./111.jpg");
// 创建FileOutputStream对象与 a.txt 关联
fos = new FileOutputStream("./222.jpg");
System.out.println("正在玩命拷贝中...");
// byte数组缓冲区
// 缓冲区大小为建议为 1024 的数
byte[] buffer = new byte[1024];
// 将字节流分批读取到byte缓冲区中并写入输出流中
int read = 0;
while ((read = fis.read(buffer)) != -1) {
// read 为每次实际读取到的字节大小 防止最后把多余的字节拷贝过来
fos.write(buffer, 0, read);
}
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭流 释放资源
// 先创建的后关闭 后创建的先关闭
if (null != fos) {
fos.close();
}
if (null != fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedOutputstream 字节缓冲输出流
基本概念
- java.io.BufferedOutputStream 类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层系统。
常用的方法
方法声明 | 功能介绍 |
---|---|
BufferedOutputStream(OutputStream out) | 根据参数指定的引用构造对象 |
BufferedOutputStream(OutputStream out, int size) | 根据参数指定的引用和缓冲区大小构造对象 |
void write(int c) | 写入单个字节 |
void write(byte[] cbuf, int off, int len) | 将指定字节数组中从偏移量o开始的len个字符写入此文件输 |
void write(byte[] cbuf) | 将 cbuf.length个字符从指定字节数组写入此文件输出流中 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
BufferedInputStream 字节缓冲输入流
基本概念
· java.Io.BufferedInputStream
类主要用于描述缓冲输入流。
常用的方法
方法声明 | 功能介绍 |
---|---|
BufferedInputStream(InputStream in) | 根据参数指定引用构造对象 |
BufferedInputStream(InputStream in, int size) | 根据参数指定引用和缓冲区大小构造对象 |
int read() | 读取单个字节的数据并返回,返回 -1 表示读取到末尾 |
int read(byte[] cbuf, int offset, int lenght) | 从输入流中将最多lenght个字节的数据读入一个字节数组中,返回读取到的字节个数,返回 -1 表示读取到末尾 |
int read(byte[] cbuf) | 从此输入流中将最多 cbuf.length 个字节的数据读入字符数组中,返回读取到的字符个数,返回 -1 表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
字节缓冲流实现文件的拷贝
public static void main(String[] args) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 创建FileInputStream对象与 a.txt 关联
bis = new BufferedInputStream(new FileInputStream("./111.jpg"));
bos = new BufferedOutputStream(new FileOutputStream("./222.jpg"));
System.out.println("正在玩命拷贝中...");
// byte数组缓冲区
// 缓冲区大小为建议为 1024 的数
byte[] buffer = new byte[1024];
// 将字节流分批读取到byte缓冲区中并写入输出流中
int read = 0;
while ((read = bis.read(buffer)) != -1) {
// read 为每次实际读取到的字节大小 防止最后把多余的字节拷贝过来
bos.write(buffer, 0, read);
bos.flush(); // 刷新流 防止字节丢失
}
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭流 释放资源
// 先创建的后关闭 后创建的先关闭
if (null != bos) {
bis.close();
}
if (null != bis) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Bufferedwriter 字符输出缓冲流
基本概念
java.io.Bufferedwriter
类主要用于写入单个字符、字符数组以及字符串到输出流中。
常用的方法
方法声明 | 功能介绍 |
---|---|
BufferedWriter(Writer out) | 根据参数指定的引用来构造对象 |
BufferedWriter(Writer out, int size) | 根据参数指定的引用和缓冲区大小来构造对象 |
void write(int c) | 写入单个字符到输出流中 |
void write(char[] cbuf, int off, int len) | 将字符数组cbuf中从下标off开始的len个字符写入输出流中 |
void write(char[] cbuf) | 将字符串数组cbuf中所有内容写入输出流中 |
void write(String S, int off, int len) | 将参数中下标从off开始的len个字符写入输出流中 |
void write(String str) | 将参数指定的字符串内容写入输出流中 |
void newLine() | 用于写入行分隔符到输出流中 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
BufferedReader 字符输入缓冲流
基本概念
java.io.BufferedReader
类用于从输入流中读取单个字符、字符数组以及字符
常用的方法
方法声明 | 功能介绍 |
---|---|
BufferedReader(Reader in) | 根据参数指定引用构造对象 |
BufferedReader(Reader in, int size) | 根据参数指定引用和缓冲区大小构造对象 |
int read() | 读取单个字节的数据并返回,返回 -1 表示读取到末尾 |
int read(byte[] cbuf, int offset, int lenght) | 从输入流中将最多lenght个字节的数据读入一个字节数组中,返回读取到的字节个数,返回 -1 表示读取到末尾 |
int read(byte[] cbuf) | 从此输入流中将最多 cbuf.length 个字节的数据读入字符数组中,返回读取到的字符个数,返回 -1 表示读取到末尾 |
String readLine() | 读取一行字符串并返回,返回null表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
OutputStreamWriter 字符转换流
基本概念
- java io.OutputStreamWriter类主要用于实现从字符流到字节流的转换。
常用的方法
方法声明 | 功能介绍 |
---|---|
OutputstreamWriter(outPutStream out) | 根据参数指定的引用来构造对象 |
OutputStreamWriter(OutputStream out, String charsetName) | 根据参数指定的引用和编码构造对象 |
void write(String str) | 将参数指定的字符串写入 |
void flush() | 刷新流 |
void close() | 用于关闭流并释放有关的资源 |
InputStreamReader 字节转换流
基本概念
- java.io.InputStreamReader 类主要用于实现从字节流到字符流的转换
常用方法
方法声明 | 功能介绍 |
---|---|
InputStream Reader(InputStream in) | 根据参数指定的引用来构造对象 |
InputStream Reader(InputStream in, String charsetName) | 根据参数指定的引用和编码来构造对象 |
int read(char[] cbuf) | 读取字符数据到参数指定的数组 |
void close() | 用于关闭流并释放有关的资源 |
ObjectoutputStrean类(重点)
基本概念
- `java.io.ObjectoutputStream 类主要用于将一个对象的所有内容整体写入到输出流中。
- 只能将支持
java.io.Serializable
接口的对象写入流中 - 类通过实现
java.io.Serializable
接口以启用其序列化功能 - 所调谓序列化主要指将一个对象需要存储的相关信息有效组织成字节序列的转化过程。
常用方法
方法声明 | 功能介绍 |
---|---|
ObjectOutputStream(OutputStream out) | 根据参数指定的引用来构造对象 |
void writeObject(Object obj) | 用于将参数指定的对象整体写入 |
void close() | 用于关闭输出流并释放有关的资源 |
ObjectInputStream类(重点)
基本概念
java.io.ObjectInputStream
类主要用于从输入流中一次性将对象整体读取出来。- 所谓反序列化主要指将有效组织的字节序列恢复为一个对象及相关信息的转化过程。
常用的方法
方法声明 | 功能介绍 |
---|---|
ObjectInputStream(InputStream in) | 根据参数指定的引用来构造对象 |
Object readObject() | 主要用于从输入流中读取一个对象并返回无法通过返回值来判断是否读取到文件的末尾 |
void close() | 用于关闭输入流并释放有关的资源 |
序列化版本号
- 序列化机制是通过在运行时判断类的 serialVersionUID来验证版本一致性的。在进行反序列化时,M会把传来的字节流中 serialVersionUID 与本地相应实体类的 serialVersionUID 进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常( Invalid CastException)
transient关键字
- transient 是java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候 transient 型变量的值不包括在串行化的表示中,然而非 transient 型的变量是被包括进去的。
建议
- 当希望将多个对象写入文件时,通常建议将多个对象放入一个集合中,然后将集合这个整体看做一个对象写入输出流中,此时只需要调用一次 readObject 方法就可以将整个集合的数据读取出来,从而避免了通过返回值。进行是否达到末尾的判断。
RandomAccessFile类
基本概念
java.io.RandomAccessFile
类主要支持对随机访问文件的读写操作。
常用的方法
方法声明 | 功能介绍 |
---|---|
RandomAccessFile(String name, String mode) | 根据参数指定的名称和模式构造对象 r:以只读方式打开 rw:打开以便读取和写入 rwd:打开以便读取和写入,同步文件内容的更新 rws:打开以便读取和写入,同步文件内容和元数据的更新 |
int read() | 读取单个字节的数据 |
void seek(long pos) | 用于设置从此文件的开头开始测量的文件指针偏移量 |
void write(int b) | 将参数指定的单个字节写入 |
void close()用于关闭流并释放有关的资源 |