IO流
一、基本分类
1、按照读写数据的基本单位不同,分为 字节流 和 字符流。
其中字节流主要指以字节为单位进行数据读写的流,可以读写任意类型的文件。
其中字符流主要指以字符(2个字节)为单位进行数据读写的流,只能读写文本文件。
2、按照读写数据的方向不同,分为 输入流 和 输出流(站在程序的角度)。
其中输入流主要指从文件中读取数据内容输入到程序中,也就是读文件。
其中输出流主要指将程序中的数据内容输出到文件中,也就是写文件。
3、按照流的角色不同分为节点流和处理流。
其中节点流主要指直接和输入输出源对接的流。
其中处理流主要指需要建立在节点流的基础之上的流。
二、体系框架
FileWriter类
java.io.FileWriter类主要用于将文本内容写入到文本文件。
方法声明 | 功能介绍 |
---|---|
FileWriter(String fileName) | 根据参数指定的文件名构造对象 |
FileWriter(String fileName, boolean append) | 以追加的方式根据参数指定的文件名来构造对象 |
void write(int c) | 写入单个字符 |
void write(char[] cbuf, int off, int len) | 将指定字符数组中从偏移量off开始的len个字符写入此文件输出流 |
void write(char[] cbuf) | 将cbuf.length个字符从指定字符数组写入此文件输出流中 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
public class FileWriterTest {
public static void main(String[] args) {
FileWriter fileWriter = null;
try {
// 1.构造FileWriter的对象与d:/a.txt文件关联
// 若文件不存在会自动创建空文件
// 若文件存在会清空文件中的原有内容
// fileWriter = new FileWriter("d:/a.txt");
// 若不想清空文件则用下面的构造方法
fileWriter = new FileWriter("d:/a.txt", true);
// 2.通过流对象写入数据内容
fileWriter.write('a');
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流对象并释放相关资源
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 length) | 从输入流中将最多len个字符的数据读入一个字符数组中,返回读取到的字符个数,返回-1表示读取到末尾 |
int read(char[] cbuf) | 从此输入流中将最多 cbuf.length 个字符的数据读入字符数组中,返回读取到的字符个数,返回-1表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
public class FileReaderTest {
public static void main(String[] args) {
FileReader fileReader = null;
try {
// 1.构造FileReader的对象与d:/a.txt文件关联
fileReader = new FileReader("d:/a.txt");
// 2.通过流对象读取数据内容
int read = fileReader.read();
System.out.println("读取到的字符:" + (char)read);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流对象并释放相关资源
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
案例:实现文件的拷贝
/**
* 实现文件的拷贝
*/
public class CopyTest {
public static void main(String[] args) {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
// 1.创建FileReader和FileWriter对象
fileReader = new FileReader("d:/a.txt");
fileWriter = new FileWriter("d:/b.txt");
// 2.读取a.txt中的内容并写入到b.txt中
int res = 0;
while ((res = fileReader.read()) != -1) {
fileWriter.write(res);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.释放资源
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileOutputStream类
java.io.FileOutputStream类主要用于将图像数据之类的原始字节流写入到输出流中。
方法声明 | 功能介绍 |
---|---|
FileOutputStream(String name) | 根据参数指定的文件名来构造对象 |
FileOutputStream(String name, boolean append) | 以追加的方式根据参数指定的文件名来构造对象 |
void write(int b) | 将指定字节写入此文件输出流 |
void write(byte[] b, int off, int len) | 将指定字节数组中从偏移量off开始的len个字节写入此文件输出流 |
void write(byte[] b) | 将 b.length 个字节从指定字节数组写入此文件输出流中 |
void flush() | 刷新此输出流并强制写出任何缓冲的输出字节 |
void close() | 关闭流对象并释放有关的资源 |
FileInputStream类
java.io.FileInputStream类主要用于从输入流中以字节流的方式读取图像数据等。
方法声明 | 功能介绍 |
---|---|
FileInputStream(String name) | 根据参数指定的文件路径名来构造对象 |
int read() | 从输入流中读取单个字节的数据并返回,返回-1表示读取到末尾 |
int read(byte[] b, int off, int len) | 从此输入流中将最多len个字节的数据读入字节数组中,返回读取到的字节个数,返回-1表示读取到末尾 |
int read(byte[] b) | 从此输入流中将最多 b.length 个字节的数据读入字节数组中,返回读取到的字节个数,返回-1表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
int available() | 获取输入流所关联文件的大小 |
案例:实现视频的拷贝
/**
* 实现视频的拷贝
*/
public class CopyPngTest {
public static void main(String[] args) {
int res = 0;
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
// 1.创建FileInputStream和FileOutputStream对象
fileInputStream = new FileInputStream("d:/模块一作业视频解题思路.wmv");
fileOutputStream = new FileOutputStream("d:/模块二作业视频解题思路.wmv");
// 2.读取03图片并复制到04图片
/*
方式一:以单个字节为单位进行拷贝
缺点:文件如果很大拷贝很慢
*/
/*while ((res =fileInputStream.read()) != -1) {
fileOutputStream.write(res);
}*/
/*
方式二:准备一个和文件大小一样的缓冲区,一次性将文件读取到缓冲区然后一次性写入
缺点:文件太大的话,无法申请更大的缓冲区
*/
/*int available = fileInputStream.available();
byte[] bytes = new byte[available];
System.out.println("拷贝中...");
fileInputStream.read(bytes);
fileOutputStream.write(bytes);
System.out.println("拷贝成功!");*/
/*
方式三:准备一个适当的缓冲区,分多次将文件拷贝完成
*/
byte[] bytes = new byte[1024];
System.out.println("拷贝中...");
while ((res = fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, res);
}
System.out.println("拷贝完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.释放资源
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
BufferedOutputStream类
java.io.BufferedOutputStream类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层
系统。
方法声明 | 功能介绍 |
---|---|
BufferedOutputStream(OutputStream out) | 根据参数指定的引用来构造对象 |
BufferedOutputStream(OutputStream out, int size) | 根据参数指定的引用和缓冲区大小来构造对象 |
void write(int b) | 写入单个字节 |
void write(byte[] b, int off, int len) | 写入字节数组中的一部分数据 |
void write(byte[] b) | 写入参数指定的整个字节数组 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
BufferedInputStream类
java.io.BufferedInputStream类主要用于描述缓冲输入流。
方法声明 | 功能介绍 |
---|---|
BufferedInputStream(InputStream in) | 根据参数指定的引用构造对象 |
BufferedInputStream(InputStream in, int size) | 根据参数指定的引用和缓冲区大小构造对象 |
int read() | 读取单个字节 |
int read(byte[] b, int off, int len) | 读取len个字节 |
int read(byte[] b) | 读取b.length个字节 |
void close() | 关闭流对象并释放有关的资源 |
案例:实现视频的拷贝
public class CopyMvmTest {
public static void main(String[] args) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
// 1.创建BufferInputStream和BufferOutputStream对象
bufferedInputStream = new BufferedInputStream(
new FileInputStream("d:/模块一作业视频解题思路.wmv"));
bufferedOutputStream = new BufferedOutputStream(
new FileOutputStream("d:/模块二作业视频解题思路.wmv"));
// 2.读取文件和写入文件
int res = 0;
while ((res = bufferedInputStream.read()) != -1) {
bufferedOutputStream.write(res);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.释放资源
if (bufferedOutputStream != null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedInputStream != null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
BufferedWriter类
java.io.BufferedWriter类主要用于写入单个字符、字符数组以及字符串到输出流中。
方法声明 | 功能介绍 |
---|---|
BufferedWriter(Writer out) | 根据参数指定的引用来构造对象 |
BufferedWriter(Writer out, int sz) | 根据参数指定的引用和缓冲区大小来构造对象 |
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) | 将参数s中下标从off开始的len个字符写入输出流中 |
void write(String str) | 将参数指定的字符串内容写入输出流中 |
void newLine() | 用于写入行分隔符到输出流中 |
void flush() | 刷新流 |
void close() | 关闭流对象并释放有关的资源 |
BufferedReader类
java.io.BufferedReader类用于从输入流中读取单个字符、字符数组以及字符串。
方法声明 | 功能介绍 |
---|---|
BufferedReader(Reader in) | 根据参数指定的引用来构造对象 |
BufferedReader(Reader in, int sz) | 根据参数指定的引用和缓冲区大小来构造对象 |
int read() | 从输入流读取单个字符,读取到末尾则返回-1,否则返回实际读取到的字符内容 |
int read(char[] cbuf, int off, int len) | 从输入流中读取len个字符放入数组cbuf中下标从off开始的位置上,若读取到末尾则返回-1,否则返回实际读取到的字符个数 |
int read(char[] cbuf) | 从输入流中读满整个数组cbuf |
String readLine() | 读取一行字符串并返回,返回null表示读取到末尾 |
void close() | 关闭流对象并释放有关的资源 |
案例:实现文件拷贝
public class BufferedCharCopyTest {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
// 1.创建BufferedReader类型的对象与d:/a.txt文件关联
br = new BufferedReader(new FileReader("d:/a.txt"));
// 2.创建BufferedWriter类型的对象与d:/b.txt文件关联
bw = new BufferedWriter(new FileWriter("d:/b.txt"));
// 3.不断地从输入流中读取一行字符串并写入到输出流中
System.out.println("正在玩命地拷贝...");
String str = null;
while ((str = br.readLine()) != null) {
bw.write(str);
bw.newLine(); // 当前系统中的行分隔符是:\r\n
}
System.out.println("拷贝文件成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放有关的资源
if (null != bw) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
PrintStream类
java.io.PrintStream类主要用于更加方便地打印各种数据内容。
方法声明 | 功能介绍 |
---|---|
PrintStream(OutputStream out) | 根据参数指定的引用来构造对象 |
void print(String s) | 用于将参数指定的字符串内容打印出来 |
void println(String x) | 用于打印字符串后并终止该行 |
void flush() | 刷新流 |
void close() | 用于关闭输出流并释放有关的资源 |
PrintWriter类
java.io.PrintWriter类主要用于将对象的格式化形式打印到文本输出流。
方法声明 | 功能介绍 |
---|---|
PrintWriter(Writer out) | 根据参数指定的引用来构造对象 |
void print(String s) | 将参数指定的字符串内容打印出来 |
void println(String x) | 打印字符串后并终止该行 |
void flush() | 刷新流 |
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类主要用于实现从字节流到字符流的转换。
方法声明 | 功能介绍 |
---|---|
InputStreamReader(InputStream in) | 根据参数指定的引用来构造对象 |
InputStreamReader(InputStream in, String charsetName) | 根据参数指定的引用和编码来构造对象 |
int read(char[] cbuf) | 读取字符数据到参数指定的数组 |
void close() | 用于关闭输出流并释放有关的资源 |
案例题目
不断地提示用户输入要发送的内容,若发送的内容是"bye"则聊天结束,否则将用户输入的内容写入到文件d:/a.txt中。
要求使用BufferedReader类来读取键盘的输入 System.in代表键盘输入
要求使用PrintStream类负责将数据写入文件
public class PrintStreamWriterTest {
public static void main(String[] args) {
// 由手册可知:构造方法需要的是Reader类型的引用,但Reader类是个抽象类,实参只能传递子类的对象 字符流
// 由手册可知: System.in代表键盘输入, 而且是InputStream类型的 字节流
BufferedReader br = null;
PrintStream ps = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
ps = new PrintStream(new FileOutputStream("d:/a.txt", true));
// 声明一个boolean类型的变量作为发送方的代表
boolean flag = true;
while(true) {
// 1.提示用户输入要发送的聊天内容并使用变量记录
System.out.println("请" + (flag? "张三": "李四") + "输入要发送的聊天内容:");
String str = br.readLine();
// 2.判断用户输入的内容是否为"bye",若是则聊天结束
if ("bye".equals(str)) {
System.out.println("聊天结束!");
break;
}
// 3.若不是则将用户输入的内容写入到文件d:/a.txt中
//else {
// 获取当前系统时间并调整格式
Date d1 = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ps.println(sdf.format(d1) + (flag?" 张三说:":" 李四说:") + str);
//}
flag = !flag;
}
ps.println(); // 写入空行 与之前的聊天记录隔开
ps.println();
ps.println();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放有关的资源
if (null != ps) {
ps.close();
}
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
ObjectOutputStream类
1、java.io.ObjectOutputStream类主要用于将一个对象的所有内容整体写入到输出流中。
2、只能将支持 java.io.Serializable 接口的对象写入流中。
3、类通过实现 java.io.Serializable 接口以启用其序列化功能。
4、所谓序列化主要指将一个对象需要存储的相关信息有效组织成字节序列的转化过程。
方法声明 | 功能结束 |
---|---|
ObjectOutputStream(OutputStream out) | 根据参数指定的引用来构造对象 |
void writeObject(Object obj) | 用于将参数指定的对象整体写入到输出流中 |
void close() | 用于关闭输出流并释放有关的资源 |
ObjectInputStream类
1、java.io.ObjectInputStream类主要用于从输入流中一次性将对象整体读取出来。
2、所谓反序列化主要指将有效组织的字节序列恢复为一个对象及相关信息的转化过程。
方法声明 | 功能介绍 |
---|---|
ObjectInputStream(InputStream in) | 根据参数指定的引用来构造对象 |
Object readObject() | 主要用于从输入流中读取一个对象并返回 无法通过返回值来判断是否读取到文件的末尾 |
void close() | 用于关闭输入流并释放有关的资源 |
3、序列化版本号
序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常(InvalidCastException)。
4、transient关键字
transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。
5、经验的分享
当希望将多个对象写入文件时,通常建议将多个对象放入一个集合中,然后将集合这个整体看做一个对象写入输出流中,此时只需要调用一次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() | 用于关闭流并释放有关的资源 |