IO流
一、IO流的概念
- IO就是Input和Output的简写,也就是输入和输出的含义。
- IO流就是指读写数据时像流水一样从一端流到另外一端,因此得名为“流"。
二、基本分类
-
按照读写数据的基本单位不同,分为 字节流 和 字符流。
-
其中字节流主要指以字节为单位进行数据读写的流,可以读写任意类型的文件。
-
其中字符流主要指以字符(2个字节)为单位进行数据读写的流,只能读写文本文件。
-
-
按照读写数据的方向不同,分为 输入流 和 输出流(站在程序的角度)。
-
其中输入流主要指从文件中读取数据内容输入到程序中,也就是读文件。
-
其中输出流主要指将程序中的数据内容输出到文件中,也就是写文件。
-
-
按照流的角色不同分为节点流和处理流。
-
其中节点流主要指直接和输入输出源对接的流。
-
其中处理流主要指需要建立在节点流的基础之上的流。
-
三、体系结构
四、相关流详解
1、FileWriter类(重点)
(1)基本概念
- java.io.FileWriter类主要用于将文本内容写入到文本文件。
(2)常用的方法
方法声明 功能介绍
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() 关闭流对象并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
public static void main(String[] args) {
// 选中代码后可以使用ctrl + alt + t来生成异常的捕获代码等
// 1.构造FileWriter类型的对象与e:/a.txt文件关联
FileWriter fw = null;
try {
// 若文件不存在该流会自动创建一个新文件
// 若文件存在该流会清空文件中的原有内容
//fw = new FileWriter("e:/a.txt");
// 以追加的方式创建对象去关联文件
// 若文件不存在则自动创建新文件
// 若文件存在则保留原有数据内容
fw = new FileWriter("e:/a.txt",true);
// 2.通过流对象写入数据内容 每当写入一个字符后则文件中的读写位置向后移动一位
fw.write('a');
// 准备一个字符数组
char[] cArr = new char[]{'h', 'e', 'l', 'l', 'o'};
// 将字符数组一部分内容写入进去
fw.write(cArr, 1,3);
// 将整个字符数组写进去
fw.write(cArr);
// 刷新流
fw.flush();
System.out.println("写入数据成");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流对象并释放有关资源
if (null != fw) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2、FileReader类(重点)
(1)基本概念
- java.io.FileReader类主要用于从文本文件读取文本数据内容。
(2)常用的方法
方法声明 功能介绍
FileReader(StringfileName) 根据参数指定的文件名构造对象
int read() 读取单个字符的数据并返回,返回-1表示读取到末尾
int read(char[] cbuf, int offset, int length) 从输入流中将最多len个字符的数据读入一个字符数组中,返回读取到的字符个 数,返回-1表示读取到末尾
int read(char[] cbuf) 从此输入流中将最多 cbuf.length 个字符的数据读入字符数组中,返回读取到 的字符个数,返回-1表示读取到末尾
void close() 关闭流对象并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
public static void main(String[] args) {
FileReader fileReader = null;
try {
// 1.构造FileReader类型的对象与e:/a.txt文件关联
fileReader = new FileReader("e:/a.txt");
// 2.读取数据内容并打印
/*
int res = fileReader.read();
System.out.println("读取到的单个字符是:" + (char)res); // 'a'
*/
/* int res = 0;
while((res = fileReader.read()) != -1) {
//res = fileReader.read();
System.out.println("读取到的单个字符是:" + (char)res); // 'a'
}*/
char[] cArr = new char[5];
// 期望读满字符数组中的一部分空间 也就是读取3个字符放入数组cArr中下标从1开始的位置上
/*int res = fileReader.read(cArr, 1, 3); // a e l
System.out.println("实际读到的字符个数是:" + res); // 3
for (char cv : cArr) {
System.out.println("读取到的单个字符是:" + cv); // 啥也没有 a e l 啥也没有
}*/
// 期望读满整个字符数组
int res = fileReader.read(cArr);
System.out.println("实际读到的字符个数是:" + res); // 5
for (char cv : cArr) {
System.out.println("读取到的单个字符是:" + cv); // a e l l h
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流文件
if (null != fileReader) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文本文件的拷贝:
package com.FirstStage.FourthModule.Two;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
public class FileCharTest {
public static void main(String[] args) {
// 1.创建FileReader类型的对象与e:/a.txt文件关联
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
fileReader = new FileReader("e:/a.txt");
//fileReader = new FileReader("e:/a.txt");
// 2.创建FileWriter类型的对象与e:/b.txt文件关联
fileWriter = new FileWriter("e:/b.txt");
//fileWriter = new FileWriter("e:/b.txt"); 拷贝图片文件失败
// 3.不断从输入流中读取数据内容并写入到输出流中
System.out.println("正在玩命的拷贝。。。。。");
int res = 0;
while ((res = fileReader.read()) != -1) {
fileWriter.write(res);
}
System.out.println("拷贝文件成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放有关资源
if (null != fileWriter) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != fileReader) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3、FileOutputStream类(重点)
(1)基本概念
- java.io.FileOutputStream类主要用于将图像数据之类的原始字节流写入到输出流中。
(2)常用的方法
方法声明 功能介绍
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() 关闭流对象并释放有关的资源
4、FileInputStream类(重点)
(1)基本概念
- java.io.FileInputStream类主要用于从输入流中以字节流的方式读取图像数据等。
(2)常用的方法
方法声明 功能介绍
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() 获取输入流所关联文件的大小
图像等文件的拷贝:
package com.FirstStage.FourthModule.Two;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileByteCopyTest {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
// 1.创建FileInputStream对象与e:/File/03 哪吒.jpg文件关联
//fileInputStream = new FileInputStream("e:/File/03 哪吒.jpg");
fileInputStream = new FileInputStream("e:/File/2017级软件工程毕业视频.mp4");
// 2.创建FileOutputStream对象与e:/File/哪吒.jpg文件关联
//fileOutputStream = new FileOutputStream("e:/File/哪吒.jpg");
fileOutputStream = new FileOutputStream("e:/File/2017级软件工程毕业视频a.mp4");
// 3.不断地从输入流中读取数据并写入到输出流中
System.out.println("正在玩命的拷贝。。。。。。");
// 方式一:以单个字节为单位进行拷贝
// 缺点:文件稍大时,拷贝的效率很低
/*int res = 0;
while((res = fileInputStream.read()) != -1) {
fileOutputStream.write(res);
}*/
// 方式二:准备一个和文件大小一样的缓冲区,一次性将文件中的所有内容读取出到缓冲区然后一次性写入进去
// 缺点:若文件过大时,无法申请和文件大小一样的缓冲区,真实物理内存不足
/*int len = fileInputStream.available();
System.out.println("获取到的文件大小为:" + len);
byte[] bArr = new byte[len];
int res = fileInputStream.read(bArr);
System.out.println("实际读取到的文件大小是:" + res);
fileOutputStream.write(bArr);*/
// 方式三:准备一个相对适当的缓冲区,分多次将文件拷贝完成
byte[] bArr = new byte[1024];
int res = 0;
while ((res = fileInputStream.read(bArr)) != -1) {
fileOutputStream.write(bArr,0, res);
}
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放资源
if (null != fileOutputStream) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != fileInputStream) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
5、BufferedOutputStream类(重点)
(1)基本概念
- java.io.BufferedOutputStream类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层系统。
(2)常用的方法
方法声明 功能介绍
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() 关闭流对象并释放有关的资源
6、BufferedInputStream类(重点)
(1)基本概念
- java.io.BufferedInputStream类主要用于描述缓冲输入流。
(2)常用的方法
方法声明 功能介绍
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() 关闭流对象并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.*;
public class BufferedCopyTest {
public static void main(String[] args) {
// 获取当前时间距离1970年1月1日0时0分0秒的毫秒数
long l1 = System.currentTimeMillis();
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
// 1.创建BufferedInputStream类型的对象与e:/File/2017级软件工程毕业视频.mp4文件关联
bufferedInputStream = new BufferedInputStream(new FileInputStream("e:/File/2017级软件工程毕业视频.mp4"));
// 2.创建BufferedOutputStream类型的对象与e:/File/2017级软件工程毕业视频a.mp4文件关联
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("e:/File/2017级软件工程毕业视频a.mp4"));
// 3.不断从输入流读取数据写入到输出流中
System.out.println("正在玩命的拷贝。。。");
/* int res = bufferedInputStream.read();
//int res = 0;
while (res(res = bufferedInputStream.read())!= -1) {
bufferedOutputStream.write(res);
}*/
byte[] bArr = new byte[1024];
int res = 0;
while ((res = bufferedInputStream.read(bArr)) != -1) {
bufferedOutputStream.write(bArr,0, res);
}
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放资源
if (null != bufferedOutputStream) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != bufferedInputStream) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long l2 = System.currentTimeMillis();
System.out.println("使用缓冲流拷贝视频文件消耗的时间为:" + (l2-l1));
}
}
7、BufferedWriter类(重点)
(1)基本概念
- java.io.BufferedWriter类主要用于写入单个字符、字符数组以及字符串到输出流中。
(2)常用的方法
方法声明 功能介绍
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() 关闭流对象并释放有关的资源
8、BufferedReader类(重点)
(1)基本概念
- java.io.BufferedReader类用于从输入流中读取单个字符、字符数组以及字符串。
(2)常用的方法
方法声明 功能介绍
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() 关闭流对象并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.*;
public class BufferedCharTest {
public static void main(String[] args) {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
// 1.创建BufferedReader类型的对象与e:/File/a.txt文件关联
bufferedReader = new BufferedReader(new FileReader("e:/File/a.txt"));
// 2.创建BufferedWriter类型的对象与e:/File/b.txt文件关联
bufferedWriter = new BufferedWriter(new FileWriter("e:/File/b.txt"));
// 3.不断的从输入流中读取一行字符串并写入到输出流中
System.out.println("正在玩命的拷贝文件。。。");
String str = null;
while ((str = bufferedReader.readLine()) != null) {
bufferedWriter.write(str);
bufferedWriter.newLine(); // 当前系统里面的行分隔符是:\r\n
}
System.out.println("拷贝文件成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放有关资源
if (null != bufferedWriter) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != bufferedReader) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
9、PrintStream类
(1)基本概念
- java.io.PrintStream类主要用于更加方便地打印各种数据内容。
(2)常用的方法
方法声明 功能介绍
PrintStream(OutputStream out) 根据参数指定的引用来构造对象
void print(String s) 用于将参数指定的字符串内容打印出来
void println(String x) 用于打印字符串后并终止该行
void flush() 刷新流
void close() 用于关闭输出流并释放有关的资源
10、PrintWriter类
(1)基本概念
- java.io.PrintWriter类主要用于将对象的格式化形式打印到文本输出流。
(2)常用的方法
方法声明 功能介绍
PrintWriter(Writer out) 根据参数指定的引用来构造对象
void print(String s) 将参数指定的字符串内容打印出来
void println(String x) 打印字符串后并终止该行
void flush() 刷新流
void close() 关闭流对象并释放有关的资源
案例题目:
- 不断地提示用户输入要发送的内容,若发送的内容是"bye"则聊天结束,否则将用户输入的内容写入到文件d:/a.txt中。
- 要求使用BufferedReader类来读取键盘的输入 System.in代表键盘输入
- 要求使用PrintStream类负责将数据写入文件
package com.FirstStage.FourthModule.Two;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PrintStreamChatTest {
public static void main(String[] args) {
// 由手册可知:构造方法需要的是一个Reader类型的引用,但Reader类是一个抽象类,实参只能传递子类的对象 字符流
// 由手册可知:System.in代表键盘输入,而且是InputStream类型的 字节流
BufferedReader bufferedReader = null;
PrintStream printStream = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
printStream = new PrintStream(new FileOutputStream("e:/File/a.txt", true));
// 声明一个boolean类型的变量作为发送方的代表
boolean flag = true;
while (true) {
// 1.提示用户输入要发送的聊天内容并使用变量记录
System.out.println("请" + (flag? "张三": "李四") + "输入要发送的聊天内容:");
String str = bufferedReader.readLine();
// 2.判断用户输入的内容是否为“bye”,若是则聊天结束
if ("bye".equals(str)) {
System.out.println("聊天结束");
break;
}
// 3.若不是则将用户输入的内容写到文件e:/File/a.txt中
// 获取当前系统时间并调整格式
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
printStream.println(simpleDateFormat.format(date) + (flag? "张三说:": "李四说:") + str);
flag = !flag;
}
printStream.println(); // 写入空行 与之前的聊天记录隔开
printStream.println();
printStream.println();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放有关的资源
if (null != printStream) {
printStream.close();
}
if (null != bufferedReader) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
11、OutputStreamWriter类
(1)基本概念
- java.io.OutputStreamWriter类主要用于实现从字符流到字节流的转换。
(2)常用的方法
方法声明 功能介绍
OutputStreamWriter(OutputStream out) 根据参数指定的引用来构造对象
OutputStreamWriter(OutputStream out, String charsetName) 根据参数指定的引用和编码构造对象
void write(String str) 将参数指定的字符串写入
void flush() 刷新流
void close() 用于关闭输出流并释放有关的资源
12、InPutStreamReader类
(1)基本概念
- java.io.InputStreamReader类主要用于实现从字节流到字符流的转换。
(2)常用的方法
方法声明 功能介绍
InputStreamReader(InputStream in) 根据参数指定的引用来构造对象
InputStreamReader(InputStream in, String charsetName) 根据参数指定的引用和编码来构造对象
int read(char[] cbuf) 读取字符数据到参数指定的数组
void close() 用于关闭输出流并释放有关的资源
13、字符编码
(1)编码表的由来
- 计算机只能识别二进制数据,早期就是电信号。为了方便计算机可以识别各个国家的文字,就需要将各个国家的文字采用数字编号的方式进行描述并建立对应的关系表,该表就叫做编码表。
(2)常见的编码表
- ASCII:美国标准信息交换码, 使用一个字节的低7位二位进制进行表示。
- ISO8859-1:拉丁码表,欧洲码表,使用一个字节的8位二进制进行表示。
- GB2312:中国的中文编码表,最多使用两个字节16位二进制为进行表示。
- GBK:中国的中文编码表升级,融合了更多的中文文字符号,最多使用两个字节16位二进制位表示。
- Unicode:国际标准码,融合了目前人类使用的所有字符,为每个字符分配唯一的字符码。所有的文字都用两个字节16位二进制位来表示。
(3)编码的发展
- 面向传输的众多 UTF(UCS Transfer Format)标准出现了,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位。这是为传输而设计的编码并使编码无国界,这样就可以显示全世界上所有文化的字符了。
- Unicode只是定义了一个庞大的、全球通用的字符集,并为每个字符规定了唯一确定的编号,具体存储成什么样的字节流,取决于字符编码方案。推荐的Unicode编码是UTF-8和UTF-16。
- UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。
14、DataOutputStream类(了解)
(1)基本概念
- java.io.DataOutputStream类主要用于以适当的方式将基本数据类型写入输出流中。
(2)常用的方法
方法声明 功能介绍
DataOutputStream(OutputStream out) 根据参数指定的引用构造对象 OutputStream类是个抽象类,实参需要传递子类对象
void writeInt(int v) 用于将参数指定的整数一次性写入输出流,优先写入高字节
void close() 用于关闭文件输出流并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamTest {
public static void main(String[] args) {
// 1.创建DataOutputStream类型的对象与e:/File/a.txt文件关联
DataOutputStream dataOutputStream = null;
try {
dataOutputStream = new DataOutputStream(new FileOutputStream("e:/File/a.txt"));
// 2.准备一个整数数据66并写入输入流
int ia = 66;
dataOutputStream.writeInt(ia); // 写入四个字节
//dataOutputStream.write(ia); // 写入一个字节
System.out.println("写入成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流对象并释放有关资源
if (null != dataOutputStream) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
15、DataInputStream类(了解)
(1)基本概念
- java.io.DataInputStream类主要用于从输入流中读取基本数据类型的数据。
(2)常用的方法
方法声明 功能介绍
DataInputStream(InputStreamin) 根据参数指定的引用来构造对象 InputStream类是抽象类,实参需要传递子类对象
int readInt() 用于从输入流中一次性读取一个整数数据并返回
void close() 用于关闭文件输出流并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class DataInputStreamTest {
public static void main(String[] args) {
// 1.创建DataInputStream类型的对象与e:/File/a.txt文件关联
DataInputStream dataInputStream = null;
try {
dataInputStream = new DataInputStream(new FileInputStream("e:/File/a.txt"));
// 2.从输入流中读取一个整数并打印
int res = dataInputStream.readInt(); // 读取四个字节
//int res = dataInputStream.read(); // 读取一个字节
System.out.println(res);
System.out.println("读取成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流对象并释放有关资源
if (null != dataInputStream) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
16、ObjectOutputStream类(重点)
(1)基本概念
- java.io.ObjectOutputStream类主要用于将一个对象的所有内容整体写入到输出流中。
- 只能将支持 java.io.Serializable 接口的对象写入流中。
- 类通过实现 java.io.Serializable 接口以启用其序列化功能。
- 所谓序列化主要指将一个对象需要存储的相关信息有效组织成字节序列的转化过程。
(2)常用的方法
方法声明 功能介绍
ObjectOutputStream(OutputStream out) 根据参数指定的引用来构造对象
void writeObject(Object obj) 用于将参数指定的对象整体写入到输出流中
void close() 用于关闭输出流并释放有关的资源
17、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方法就可以将整个集合的数据读取出来,从而避免了通过返回值进行是否达到文件末尾的判断。
package com.FirstStage.FourthModule.Two;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1917139850630783142L;
private String userName; // 用于描述用户名
private String password; // 用于描述用户密码
private transient String phoneNum; // 用于描述用户手机号码 该成员变量不参与序列化操作
public User() {
}
public User(String userName, String password, String phoneNum) {
this.userName = userName;
this.password = password;
this.phoneNum = phoneNum;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", password='" + password + '\'' +
", phoneNum='" + phoneNum + '\'' +
'}';
}
}
package com.FirstStage.FourthModule.Two;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamTest {
public static void main(String[] args) {
// 1.创建ObjectOutputStream类型的对象与e:/File/a.txt文件关联
ObjectOutputStream objectOutputStream= null;
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("e:/File/a.txt"));
// 2.准备一个User类型的对象并初始化
User user = new User("赵云", "123456", "17315778888");
// 3.将整个User类型的对象写入输出流
objectOutputStream.writeObject(user);
System.out.println("写入成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流对象并释放有关资源
if (null != objectOutputStream) {
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.FirstStage.FourthModule.Two;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamTest {
public static void main(String[] args) {
// 1.创建ObjectInputStream类型的对象与e:/File/a.txt文件关联
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(new FileInputStream("e:/File/a.txt"));
// 2.从输入流中读取一个对象并打印
Object readObject = objectInputStream.readObject();
System.out.println("读取到的对象是:" + readObject);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// 3.关闭流并释放相关资源
if (null != objectInputStream) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
18、RandomAccessFile类
(1)基本概念
- java.io.RandomAccessFile类主要支持对随机访问文件的读写操作。
(2)常用的方法
方法声明 功能介绍
RandomAccessFile(String name, Stringmode) 根据参数指定的名称和模式构造对象,r: 以只读方式打开
rw:打开以便读取和写入
rwd:打开以便读取和写入,同步文件内容的更新
rws:打开以便读取和写入,同步文件内容和元数据的更新
int read() 读取单个字节的数据
void seek(long pos) 用于设置从此文件的开头开始测量的文件指针偏移量
void write(int b) 将参数指定的单个字节写入
void close() 用于关闭流并释放有关的资源
package com.FirstStage.FourthModule.Two;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) {
// 1.创建RandomAccessFile类型的对象与e:/File/a.txt文件关联
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile("e:/File/a.txt", "rw");
// 2.对文件内容进行随机读写操作
// 设置距离文件开头位置的偏移量,从文件开头位置向后偏移3个字节 aellhello
randomAccessFile.seek(3);
int res = randomAccessFile.read();
System.out.println("读取到的字符是:" + (char)res);
res = randomAccessFile.read();
System.out.println("读取到的字符是:" + (char)res);
randomAccessFile.write('2'); // 执行改行代码后覆盖了字符e
System.out.println("写入数据成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3.关闭流对象并释放有关资源
if (null != randomAccessFile) {
try {
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
本文来自博客园,作者:寒露凝珠,转载请注明原文链接:https://www.cnblogs.com/china-soldier/p/15007077.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现