IO流介绍
IO:输入/输出(Input/Output)
流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
IO流的分类
IO流就是用来处理设备间数据传输问题的。常见的应用:文件复制;文件上传;文件下载
按照数据的流向
输入流:读数据
输出流:写数据
按照数据类型来分
字节流 字节输入流 字节输出流
字符流 字符输入流 字符输出流
IO流的使用场景
如果操作的是纯文本文件,优先使用字符流
如果操作的是图片、视频、音频等二进制文件。优先使用字节流
如果不确定文件类型,优先使用字节流。字节流是万能的流。
IO流小结
小结:字节流可以复制任意文件数据,有4种方式一般采用字节缓冲流一次读写一个字节数组的方式
小结:字符流只能复制文本数据,有5种方式,一般采用字符缓冲流的特有功能
习题
package com.itxuexi.it18.IOex01;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
//把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个集合元素
public class TxtToArrayListDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("G:\\javaSE_code\\ArrayTest02.java"));
//创建ArrayList集合对象
ArrayList<String> arr = new ArrayList<String>();
//调用字符缓冲输入流对象的方法读数据
String line;
while ((line = br.readLine()) != null){
//把读取到的字符串数据存储到集合中
arr.add(line);
}
br.close();
//遍历集合
for(String s:arr){
System.out.println(s);
}
}
}
package com.itxuexi.it18.IOex01;
//把ArrayList集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class TxtToArrayListDemo02 {
public static void main(String[] args) throws IOException {
//创建ArrayList集合
ArrayList<String> arr = new ArrayList<String>();
//往集合中添加元素
arr.add("hello");
arr.add("world");
arr.add("java");
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\javaSE_code\\ArrayTest02.java"));
//遍历集合,得到每一个字符串数据
for(String s: arr){
//调用字符缓冲输出流对象的方法写数据
bw.write(s);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
package com.itxuexi.it18.IOex01;
//我有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随点名器
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
public class CallNameDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("G:\\javaSE_code\\ArrayTest02.java"));
//创建ArrayList集合对象
ArrayList<String> arr = new ArrayList<String>();
//调用字符缓冲输入流对象的方法读数据
String line;
while ((line = br.readLine()) != null){
arr.add(line);
}
//释放资源
br.close();
//用Random产生一个随机数,随机数的范围在:[0,集合的长度)
Random r = new Random();
int index = r.nextInt(arr.size());
//把第6步产生的随机数作为索引到ArrayList集合中获取值
String name = arr.get(index);
System.out.println(" 幸运者是:" + name);
}
}
集合到文件改进版
package com.itxuexi.it18.IOex02;
public class Student {
private String number;
private String name;
private int age;
private String add;
public Student() {
}
public Student(String number, String name, int age,String add) {
this.number = number;
this.name = name;
this.age = age;
this.add = add;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
}
//------------------------------------------------------------------------
package com.itxuexi.it18.IOex02;
/*
把ArrayList集合中的学生数据写入到文本文件。要求:每一个学生对象的数据作为文件中的一行数据 格式:
学号,姓名,年龄,居住地 举例:itheima001,林青霞,30,西安
*/
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class ArrayListToTxtDemo {
public static void main(String[] args) throws IOException {
//创建ArrayList集合
ArrayList<Student> arr = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("001","liliy",15,"西安");
Student s2 = new Student("002","shily",12,"广西");
Student s3 = new Student("003","Tike",16,"安徽");
Student s4 = new Student("004","mikey",11,"河南");
//把学生对象添加到集合中
arr.add(s1);
arr.add(s2);
arr.add(s3);
arr.add(s4);
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\javaSE_code\\fos.txt"));
//遍历集合,得到每一个学生对象
for(Student s : arr){
//把学生对象的数据拼接成指定格式的字符串
StringBuilder sb = new StringBuilder();
sb.append(s.getNumber()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAdd());
//调用字符缓冲输出流对象的方法写数据
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
package com.itxuexi.it18.IOex02;
/*
把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个学生对象的成员变量值
举例:itheima001,林青霞,30,西安
*/
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class FileToArrayListDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("G:\\javaSE_code\\fos.txt"));
//创建ArrayList集合对象 (Student同上次)
ArrayList<Student> arr = new ArrayList<Student>();
//调用字符缓冲输入流对象的方法读数据
String len;
while ((len = br.readLine()) != null) {
//把读取到的字符串数据用split()进行分割,得到一个字符串数组
String [] strArr = len.split(",");
//创建学生对象
Student s = new Student();
//把字符串数组中的每一个元素取出来对应的赋值给学生对象的成员变量值
s.setNumber(strArr[0]);
s.setName(strArr[1]);
s.setAge(Integer.parseInt(strArr[2]));
s.setAdd(strArr[3]);
//把学生对象添加到集合
arr.add(s);
}
//释放资源
br.close();
//遍历集合
for(Student s : arr){
System.out.println(s.getNumber() + "," + s.getName() + "," + s.getAge() + "," + s.getAdd());
}
}
}
IO流案例
- 集合到文件数据排序改进版
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件
格式:姓名,语文成绩,数学成绩,英语成绩 举例:林青霞,98,99,100
package com.itxuexi.it19.ioEx01;
public class Student {
private String name;
private int chinese;
private int math;
private int english;
public Student() {
}
public Student(String name, int chinese, int math, int english) {
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
//总分
public int getSum(){
return chinese + math + english;
}
}
//--------------------------------------------------------
package com.itxuexi.it19.ioEx01;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/*
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件
格式:姓名,语文成绩,数学成绩,英语成绩 举例:林青霞,98,99,100
*/
public class TreeSetToFileDemo {
public static void main(String[] args) throws IOException {
//创建TreeSet集合,通过比较器排序进行排序
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//成绩总分从高到低
int num = s2.getSum() - s1.getSum();
//次要条件
int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
int num4 = num3 == 0 ? s1.getName().compareTo(s2.getName()) : num3;
return num4;
}
});
//键盘录入学生数据
for(int i=0;i<5;i++){
Scanner sc = new Scanner(System.in);
System.out.println("第" + (i+1) + "个学生信息");
System.out.println("请输入姓名:");
String name = sc.nextLine();
System.out.println("语文:");
int chinese = sc.nextInt();
System.out.println("数学:");
int math = sc.nextInt();
System.out.println("英语:");
int english = sc.nextInt();
//创建学生对象,把键盘录入的数据对应赋值给学生对象的成员变量
Student s = new Student();
s.setName(name);
s.setChinese(chinese);
s.setMath(math);
s.setEnglish(english);
//把学生对象添加到TreeSet集合
ts.add(s);
}
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\javaSE_code\\foss.txt"));
//遍历集合,得到每一个学生对象
for(Student s: ts){
//把学生对象的数据拼接成指定格式的字符串
StringBuilder sb = new StringBuilder();
sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",").append(s.getEnglish());
//调用字符缓冲输出流对象的方法写数据
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
- 复制单级文件夹【应用】
报错:NullPointerException
package com.itxuexi.it19.ioEx02;
/*
把“E:\itcast”这个文件夹复制到模块目录下
创建数据源目录File对象,路径是E:\itcast
2. 获取数据源目录File对象的名称
3. 创建目的地目录File对象,路径由(模块名+第2步获取的名称)组成
4. 判断第3步创建的File是否存在,如果不存在,就创建
5. 获取数据源目录下所有文件的File数组
6. 遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
7. 获取数据源文件File对象的名称
8. 创建目的地文件File对象,路径由(目的地目录+第7步获取的名称)组成
9. 复制文件
由于不清楚数据源目录下的文件都是什么类型的,所以采用字节流复制文件
采用参数为File的构造方法
*/
import java.io.*;
public class CopyFolderDemo {
public static void main(String[] args) throws IOException {
//创建数据源目录File对象,路径是E:\\itcast
File srcFolder = new File("G:\\javaSE_code\\text");
//获取数据源目录File对象的名称(itcast)
String srcFolderName = srcFolder.getName();
//创建目的地目录File对象,路径名是模块名+itcast组成(myCharStream\\itcast)
File descFolder = new File("text2",srcFolderName);
//判断目的地目录对应的File是否存在,如果不存在,就创建
if (!descFolder.exists()) {
descFolder.mkdir();
}
//获取数据源目录下所有文件的File数组
File[] listFiles = srcFolder.listFiles();
//遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
for (File srcFile : listFiles) {
//获取数据源文件File对象的名称(mn.jpg)
String srcFileName = srcFile.getName();
//创建目的地文件File对象,路径名是目的地目录+mn.jpg组成
File destFile = new File(descFolder, srcFileName);
//复制文件
copyFile(srcFile,destFile);
}
}
public static void copyFile(File srcFile, File destFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bis.close();
bos.close();
}
}
-
复制多级文件夹
把“E:\itcast”这个文件夹复制到 F盘目录下
package com.itxuexi.it19.ioEx02;
/*
1. 创建数据源File对象,路径是E:\itcast
2. 创建目的地File对象,路径是F:\
3. 写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
4. 判断数据源File是否是文件
是文件:直接复制,用字节流
不是文件:
在目的地下创建该目录
遍历获取该目录下的所有文件的File数组,得到每一个File对象
回到3继续(递归)
*/
import java.io.*;
//复制多级文件夹
public class CopyFoldersDemo {
public static void main(String[] args) throws IOException{
//创建数据源File对象,路径是E:\\itcast
File srcFile = new File("G:\\javaSE_code\\test");
//创建目的地File对象,路径是F:\\
File destFile = new File("G:\\javaSE_code\\test2");
//写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
copyFolder(srcFile, destFile);
}
//复制文件夹
private static void copyFolder(File srcFile, File destFile) throws IOException
{
//判断数据源File是否是目录
if(srcFile.isDirectory()) {
//在目的地下创建和数据源File名称一样的目录
String srcFileName = srcFile.getName();
File newFolder = new File(destFile,srcFileName); //F:\\itcast
if(!newFolder.exists()) {
newFolder.mkdir();
}
//获取数据源File下所有文件或者目录的File数组
File[] fileArray = srcFile.listFiles();
//遍历该File数组,得到每一个File对象
for(File file : fileArray) {
//把该File作为数据源File对象,递归调用复制文件夹的方法
copyFolder(file,newFolder);
}
} else {
//说明是文件,直接复制,用字节流
File newFile = new File(destFile,srcFile.getName());
copyFile(srcFile,newFile);
}
}
//字节缓冲流复制文件
private static void copyFile(File srcFile, File destFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
}
- 复制文件的异常处理
package com.itxuexi.it19.ioEx02;
import javax.imageio.IIOException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//复制文件的异常处理
try...catch...finally
public class CopyFileDemo01 {
public static void main(String[] args) throws IOException {
// method1();
// method2();
// method3();
method4();
}
//JDK9的改进方案
private static void method4() throws IOException{
FileReader fr = new FileReader("fr.txt");
FileWriter fw = new FileWriter("fw.txt");
try(fr;fw){
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) !=-1){
fw.write(chs,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
}
//JDK7的改进方案
private static void method3() throws IOException {
try (FileReader fr = new FileReader("fr.txt");
FileWriter fw = new FileWriter("fw.txt");) {
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//try...catch...finally
private static void method2() throws IOException {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("fr.txt");
fw = new FileWriter("fw.txt");
char[] chr = new char[1024];
int len;
while ((len = fr.read(chr)) != -1) {
fw.write(chr, 0, len);
}
} catch (IIOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//抛出处理
private static void method1() throws IOException {
FileReader fr = new FileReader("fr.txt");
FileWriter fw = new FileWriter("fw.txt");
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
}
fw.close();
fr.close();
}
}
IO特殊操作流
标准输入流
public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
- 自己实现键盘录入数据
package com.itxuexi.it19.ioEx03;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
/*标准输入流
public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
*/
public class SystemInDemo {
public static void main(String[] args) throws IOException {
/*
InputStream is = System.in;
//输入中文会乱
// int by;
// while ((by=is.read())!=-1){
// System.out.print((char)by);
// }
//如何把字节流转换为字符流?用转换流
InputStreamReader isr = new InputStreamReader(is);
//使用字符流能不能够实现一次读取一行数据呢?可以;但是,一次读取一行数据的方法是字符缓冲输入流的特有方法
BufferedReader br = new BufferedReader(isr);
*/
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一个字符串:");
String line = br.readLine();
System.out.println("你输入的字符串是:" + line);
System.out.println("请输入一个整数:");
int i = Integer.parseInt(br.readLine()); //字符串转换为整数,其他类型也可以以此方法转换
System.out.println("你输入的整数是:" + i);
//自己实现键盘录入数据太麻烦了,所以Java就提供了一个类供我们使用
Scanner sc = new Scanner(System.in);
}
}
标准输出流
- 输出语句的本质:是一个标准的输出流
PrintStream ps = System.out;
PrintStream类有的方法,System.out都可以使用
package com.itxuexi.it19.ioEx03;
import java.io.PrintStream;
public class SystemInDemo2 {
public static void main(String[] args) {
PrintStream ps = System.out;
//能够方便地打印各种数据值
ps.print("hello");
ps.print(100);
ps.println("hello");
ps.println(100);
//System.out的本质是一个字节输出流
System.out.println("hello");
System.out.println(100);
}
}
字节打印流
打印流分类
字节打印流:PrintStream
字符打印流:PrintWriter
打印流的特点
只负责输出数据,不负责读取数据
永远不会抛出IOException
有自己的特有方法
字节打印流:
PrintStream(String fileName):使用指定的文件名创建新的打印流
使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出
以改变输出语句的目的地 public static void setOut(PrintStream out):重新分配“标准”输出流
package com.itxuexi.it19.ioEx03;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamDemo1 {
public static void main(String[] args) throws IOException {
//PrintStream(String fileName):使用指定的文件名创建新的打印流
PrintStream ps = new PrintStream("G:\\javaSE_code\\test2\\ps.txt");
//写数据
//字节输出流有的方法
ps.write(97);
//使用特有方法写数据
ps.print(98);
ps.println();
ps.print(99);
//释放资源
ps.close();
}
}
字符打印流
字符打印流构造方法
PrintWriter(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新
PrintWriter(Writer out, boolean autoFlush):创建一个新的PrintWriter out:字符输出流 autoFlush: 一个布尔值,如果 为真,则println , printf ,或format方法将刷新输出缓冲区
package com.itxuexi.it19.ioEx03;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
//字符打印流
public class PrintWriterDemo2 {
public static void main(String[] args) throws IOException {
/*
//PrintWriter(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新
PrintWriter pw = new PrintWriter("G:\\javaSE_code\\test2\\ps.txt");
pw.write("hello"); //字符流,需要刷新才显示
pw.write("\r\n");
pw.flush();
pw.write("world");
pw.flush();
pw.println("hello"); // 相当于 pw.write("hello"); pw.write("\r\n");
pw.flush();
*/
//自动刷新且换行;true
PrintWriter pw = new PrintWriter(new FileWriter("G:\\javaSE_code\\test2\\ps.txt"),true);
pw.println("hello");
/* 等同于下三行
pw.write("hello"); //字符流,需要刷新才显示
pw.write("\r\n");
pw.flush();
*/
pw.println("world");
pw.close();
}
}
复制Java文件打印流改进版
package com.itxuexi.it19.ioEx03;
import java.io.*;
//2.5复制Java文件打印流改进版【应用】
public class CopyJavaDemo {
public static void main(String[] args) throws IOException {
/*
//根据数据源创建字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("G:\\javaSE_code\\ArrayTest02.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\javaSE_code\\test2\\copy.java"));
//读写数据,复制文件
String line;
while ((line = br.readLine()) !=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
br.close();
bw.close();
*/
//根据数据源创建字符输入流对象 (改进)
BufferedReader br = new BufferedReader(new FileReader("G:\\javaSE_code\\ArrayTest02.java"));
//根据目的地创建字符输出流对象
PrintWriter pw = new PrintWriter(new FileWriter("G:\\javaSE_code\\test2\\copy.java"), true);
//读写数据,复制文件
String ling;
while ((ling = br.readLine()) != null) {
pw.println(ling);
}
//释放资源
br.close();
pw.close();
}
}
对象序列化流
对象序列化介绍:
- 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
- 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存 储的属性等信息
- 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
- 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
对象序列化流: ObjectOutputStream
- 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对 象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或 另一个进程中重构对象
构造方法:
ObjectOutputStream(OutputStream out) :创建一个写入指定的OutputStream的 ObjectOutputStream
序列化对象的方法:
void writeObject(Object obj) :将指定的对象写入ObjectOutputStream
package com.itxuexi.it19.ioEx04;
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//--------------------------------------------
package com.itxuexi.it19.ioEx04;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\javaSE_code\\fos.txt"));
//创建Student对象
Student s = new Student("张三",11);
//void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s); //对象必须实现 Serializable 接口 ;文本乱码,需要反序列化查看
//释放资源
oos.close();
}
}
对象反序列化流
package com.itxuexi.it19.ioEx04;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamDemo02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("G:\\javaSE_code\\fos.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
serialVersionUID&transient
serialVersionUID
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
- 会出问题,会抛出InvalidClassException异常
如果出问题了,如何解决呢?
-
重新序列化
-
给对象所属的类加一个serialVersion
- private static final long serialVersionUID = 42L;
transient
- 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
- 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
package com.itxuexi.it19.ioEx05;
import java.io.Serializable;
public class Student implements Serializable {
//给一个固定序列值
private static final long serialVersionUID = 42L;
private String name;
// private int age;
//transient 修饰的不参与序列化过程
private transient int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// @Override
// public String toString() {
// return "Student{" +
// "name='" + name + '\'' +
// ", age=" + age +
// '}';
// }
}
//------------------------------------
package com.itxuexi.it19.ioEx05;
/*
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
运行完成后,再student类增加toString时报错
java.io.InvalidClassException:
com.itxuexi.it19.ioEx05.Student; local class incompatible:
stream classdesc serialVersionUID = 7664368107817872699,
local class serialVersionUID = 6008181740025609173
如果出问题了,如何解决呢?
重新序列化
给对象所属的类加一个serialVersion : private static final long serialVersionUID = 42L;
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
/transient 修饰的不参与序列化过程
private transient int age; 给默认值0 --int类型
*/
import java.io.*;
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// write();
read();
}
//反序列化
public static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("G:\\javaSE_code\\fos.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
//序列化
public static void write() throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\javaSE_code\\fos.txt"));
Student s = new Student("王遗风", 15);
oos.writeObject(s);
oos.close();
}
}