12 IO流
12 IO流
12.1 File类
12.1.1 引入
【1】文件,文件夹(目录)
【2】查看文件/目录的信息
右键-属性
【3】在java程序中操纵文件/目录?怎么办?
java程序,最典型的特点:面向对象,java程序最擅长的就是操纵对象,这个对象属于File类。
12.1.2 对文件进行操作
package com.liweixiao.file;
import java.io.File;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//将文件封装为一个File类对象
File f = new File("e:\\test.txt");
File f1 = new File("e:\\test.txt");
File f2 = new File("e:/test.txt");
//File.separator获取当前操作系统的路径拼接符号
File f3 = new File("e:"+File.separator+"test.txt");//建议使用这种
//常用方法
System.out.println("文件是否可读:"+f.canRead());
System.out.println("文件是否可写:"+f.canWrite());
System.out.println("文件名称:"+f.getName());
System.out.println("文件上级目录:"+f.getParent());
System.out.println("是否目录:"+f.isDirectory());
System.out.println("是否文件:"+f.isFile());
System.out.println("文件是否隐藏:"+f.isHidden());
System.out.println("文件大小:"+f.length());
System.out.println("是否存在:"+f.exists());
/*if(f.exists()){//如果文件存在,删除文件
f.delete();
}else {//如果文件不存在,创建文件
f.createNewFile();
}*/
System.out.println(f == f1);//比较两个对象的地址
System.out.println(f.equals(f1));//比较两个对象对应的文件路径
//跟路径相关
System.out.println("文件绝对路径:"+f.getAbsolutePath());
System.out.println("文件相对路径:"+f.getPath());
System.out.println("toString:"+f.toString());
File f5 = new File("demo.txt");
if(! f5.exists()){
f5.createNewFile();
}
System.out.println("文件绝对路径:"+f5.getAbsolutePath());
System.out.println("文件相对路径:"+f5.getPath());
System.out.println("toString:"+f5.toString());
File f6 = new File("a/b/c/demo.txt");
/*if(! f6.exists()){
f6.createNewFile();
}*/
System.out.println("文件绝对路径:"+f6.getAbsolutePath());
System.out.println("文件相对路径:"+f6.getPath());
System.out.println("toString:"+f6.toString());
}
}
12.1.3 对目录进行操作
package com.liweixiao.file;
import java.io.File;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test02 {
public static void main(String[] args) {
//将目录封装为File类的对象
File f = new File("E:\\hw\\IdeaProjects");
//常用方法
System.out.println("是否可读:"+f.canRead());
System.out.println("是否可写:"+f.canWrite());
System.out.println("名称:"+f.getName());
System.out.println("上级目录:"+f.getParent());
System.out.println("是否目录:"+f.isDirectory());
System.out.println("是否文件:"+f.isFile());
System.out.println("是否隐藏:"+f.isHidden());
System.out.println("大小:"+f.length());
System.out.println("是否存在:"+f.exists());
//跟路径相关
System.out.println("绝对路径:"+f.getAbsolutePath());
System.out.println("相对路径:"+f.getPath());
System.out.println("toString:"+f.toString());
//跟目录相关的方法:
File f2 = new File("E:\\a\\b\\c");
//创建目录
//f2.mkdir();//创建单层目录
//f2.mkdirs();//创建多层目录
//删除目录
f2.delete();//删除目录,只会删除一层,前提:这层目录是空的,没有子目录或文件。
//查看
System.out.println("/////////////");
String[] list = f.list();//文件夹下目录/文件的数组
for(String s:list){
System.out.println(s);
}
System.out.println("--------------");
File[] files = f.listFiles();//作用更加广泛
for(File file:files){
System.out.println(file.getName()+","+file.getAbsolutePath());
}
}
}
12.2 IO流
12.2.1 引入
【1】File类:封装文件/目录的各种信息,对目录/文件进行操作,但是不能获取文件/目录中的内容
【2】引入IO流
I/O:Input/Output的缩写,用于处理设备之间的数据的传输。
【3】理解:一根管
以上图片来自网络
【4】IO流的体系结构
以上图片来自网络
12.2.2 FileReader、FileWriter字符流
【FileReader输入字符流】
【1】一个字符一个字符的将文件中内容读取到程序中
package com.liweixiao.io01;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//文件->程序
//1.有一个文件->创建一个file类的对象
File f = new File("e:\\test.txt");
//2.利用FileReader,怼到源文件->创建FileReader流的对象
FileReader fr = new FileReader(f);
//3.进行“吸”的动作->读取动作
/*int n1 = fr.read();
System.out.println(n1);
int n2 = fr.read();
System.out.println(n2);
int n3 = fr.read();
System.out.println(n3);
int n4 = fr.read();
System.out.println(n4);
int n5 = fr.read();
System.out.println(n5);
int n6 = fr.read();
System.out.println(n6);//文件的结尾处,读取内容为-1*/
//方式1
/*int n = fr.read();
while (n != -1){
System.out.println(n);
n=fr.read();
}*/
//方式2
int n;
while ((n=fr.read()) != -1){
System.out.println("uncode:"+n+",字符:"+(char)n);
}
//4.“管”不用了关闭->关闭流
//流、数据库、网络资源,靠jvm本身没有办法自动关闭,需要程序员手动关闭
fr.close();
}
}
【2】一次性读取多个字符,缓冲数组
package com.liweixiao.io01;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test02 {
public static void main(String[] args) throws IOException {
//文件->程序
//1.创建一个file类的对象
File f = new File("e:\\test.txt");
//2.创建FileReader流的对象
FileReader fr = new FileReader(f);
//3.读取动作
//引入一个“快递员的小车”,一次拉5个快递
char[] ch = new char[5];
int len = fr.read(ch);//一次读取五个,返回这个数组中的有效长度
while (len != -1){//文件的结尾处,读取内容为-1
//错误方式
/*for (int i = 0; i < ch.length; i++) {
System.out.println(ch[i]);
}*/
//正确方式1
/*for (int i = 0; i < len; i++) {
System.out.print(ch[i]);
}*/
//正确方式2
String s = new String(ch,0,len);
System.out.print(s);
len=fr.read(ch);
}
// 4.关闭流
fr.close();
}
}
【FileWriter字符流输出字符流】
【1】一个字符一个字符的向外输出
package com.liweixiao.io01;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test03 {
public static void main(String[] args) throws IOException {
//1.有一个目标文件
File f = new File("e:\\demo.txt");
//2.输出流
FileWriter fw = new FileWriter(f);//1.目标文件不存在,会自动创建文件。
//FileWriter fw = new FileWriter(f,false);//目标文件存在,默认false覆盖操作。
//FileWriter fw = new FileWriter(f,true);//目标文件不存在,设置true追加操作。
//3.输出
//一个字符一个字符的输出
String str = "hello你好";
for (int i = 0; i < str.length(); i++) {
fw.write(str.charAt(i));
}
//4.关闭流
fw.close();
}
}
【2】一次性写多个字符的向外输出,利用缓冲数组
package com.liweixiao.io01;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test04 {
public static void main(String[] args) throws IOException {
//1.有一个目标文件
File f = new File("e:\\demo.txt");
//2.输出流
FileWriter fw = new FileWriter(f);
//3.输出
//一次多个字符输出,利用缓冲数组
String str = "abchello你好老师";
char[] chars = str.toCharArray();
fw.write(chars);
//4.关闭流
fw.close();
}
}
【3】利用FileReader、FileWriter文件复制
package com.liweixiao.io01;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test04 {
public static void main(String[] args) throws IOException {
//1.有一个源文件
File f1 = new File("e:\\test.txt");
//2.有一个目标文件
File f2 = new File("e:\\demo.txt");
//3.搞一个输入的管,怼到源文件
FileReader fr = new FileReader(f1);
//4.搞一个输出的管,怼到目标文件
FileWriter fw = new FileWriter(f2);
//5.开始读取
//方式1:一个字符一个字符的复制
/*int n=fr.read();
while (n != -1){
fw.write(n);
n = fr.read();
}*/
//方式2:利用一个缓冲数组
/*char[] ch = new char[5];
int len = fr.read(ch);
while (len != -1){
fw.write(ch,0, len);
len =fr.read(ch);
}*/
//方式3:利用一个缓冲数组,将数组转成字符串
char[] ch = new char[5];
int len = fr.read(ch);
while (len != -1){
String s = new String(ch, 0, len);
fw.write(s);
len=fr.read(ch);
}
//6.关闭流,倒着关闭,后用先关
fw.close();
fr.close();
}
}
警告-不要用字符流去操作非文本文件
文本文件:.txt、.java、.c、.cpp,建议使用字符流操作
非文本文件:.jpg、.mp3、.MP4、.doc、.ppt,建议使用字节流操作
12.3 利用try-catch-finally处理异常方式
实际开发中,使用try-catch解决异常
package com.liweixiao.io01;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/1/11
* @description:
*/
public class Test04 {
public static void main(String[] args) {
//1.有一个源文件
File f1 = new File("e:\\test.txt");
//2.有一个目标文件
File f2 = new File("e:\\demo.txt");
//3.搞一个输入的管,怼到源文件
FileReader fr = null;
FileWriter fw=null;
try {
fr = new FileReader(f1);
//4.搞一个输出的管,怼到目标文件
fw = new FileWriter(f2);
//5.开始读取
//方式3:利用一个缓冲数组,将数组转成字符串
char[] ch = new char[5];
int len = fr.read(ch);
while (len != -1){
String s = new String(ch, 0, len);
fw.write(s);
len=fr.read(ch);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//6.关闭流,倒着关闭,后用先关
try {
if(fw != null){
fw.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if(fr != null){
fr.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
12.2.3 FileInputStream、FileOutputStream字节流
【FileInputStream字节流读取文件中内容】
【1】字节流读取文本文件
package com.liweixiao.io02;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/12
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//1.源文件
File f = new File("e:\\test.txt");
//2.搞一根管怼到源文件
FileInputStream fis = new FileInputStream(f);
//3.读取
/*
细节1:文件是utf-8存储的,英文占1个字节,中文占3个字节。
细节2:如果是文本文件,不要使用字节流,建议使用字节流。
细节3:read()读取一个字节,返回值是int类型,不是byte类型。
byte取值范围-128~127。read()底层做了处理,返回都是正数,避免返回-1。
*/
int n = fis.read();
while (n != -1){
System.out.println(n+","+(char)n);
n=fis.read();
}
//4.关闭流
fis.close();
}
}
【2】字节流读取非文本文件(以图片为例),一个一个字节读取
package com.liweixiao.io02;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/12
* @description:
*/
public class Test02 {
public static void main(String[] args) throws IOException {
//1.源文件
File f = new File("e:\\test.jpg");
//2.字节流的管
FileInputStream fis = new FileInputStream(f);
//3.读取
int count=0;
int n = fis.read();
while (n != -1){
System.out.println(n);
n=fis.read();
count++;
}
System.out.println("字节:"+count);
//4.关闭流
fis.close();
}
}
【3】利用缓冲数组
package com.liweixiao.io02;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/1/12
* @description:
*/
public class Test03 {
public static void main(String[] args) throws IOException {
//1.源文件
File f = new File("e:\\test.jpg");
//2.字节流的管
FileInputStream fis = new FileInputStream(f);
//3.读取
byte[] b = new byte[1024*6];
int len = fis.read(b);
while (len != -1){
for (int i = 0; i < len; i++) {
System.out.println(b[i]);
}
len =fis.read(b);
}
//4.关闭流
fis.close();
}
}
【FileInputStream、FileOutputStream完成非文本文件的复制】
【1】读入一个字节,写出一个字节
package com.liweixiao.io02;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/2
* @description:
*/
public class Test04 {
public static void main(String[] args) throws IOException {
//功能:完成图片的复制
//1.原文件
File f1 = new File("e:\\test.jpg");
//2.目标文件
File f2 = new File("e:\\test1.jpg");
//3.一根输入管,怼到源文件
FileInputStream fis = new FileInputStream(f1);
//4.一根输出管,怼到目标文件
FileOutputStream fos = new FileOutputStream(f2);
//5.开始复制,边读边写
int n = fis.read();
while (n != -1){
fos.write(n);
//System.out.println(n);
n = fis.read();
}
//6.关闭流,倒着关
fos.close();
fis.close();
}
}
【2】利用缓冲字节数组,批量复制
package com.liweixiao.io02;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author:LiWeixiao
* @date:2023/2/2
* @description:
*/
public class Test05 {
public static void main(String[] args) throws IOException {
//功能:完成图片的复制
//1.原文件
File f1 = new File("e:\\test.jpg");
//2.目标文件
File f2 = new File("e:\\test1.jpg");
//3.一根输入管,怼到源文件
FileInputStream fis = new FileInputStream(f1);
//4.一根输出管,怼到目标文件
FileOutputStream fos = new FileOutputStream(f2);
//5.开始复制,边读边写
//利用缓冲数组
byte[] b = new byte[1024 * 8];
int len = fis.read(b);
while (len != -1){
fos.write(b,0, len);
//System.out.println(len);
len =fis.read(b);
}
//6.关闭流,倒着关
fos.close();
fis.close();
}
}
12.2.4 BufferedInputStream、BufferedOutputStream缓冲字节流
【1】读入一个字节,写出一个字节
【2】利用缓冲字节数组
【3】利用缓冲区
以上图片来自网络
想要完成上面的效果,使用FileInputStream、FileOutputStream不能实现。
需要功能的加强,需要引入新的流,在FileInputStream、FileOutputStream外面再套一层流,BufferedInputStream、BufferedOutputStream缓冲流/处理流
package com.liweixiao.io02;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/8
* @description:
*/
public class Test06 {
public static void main(String[] args) throws IOException {
//1.原图片
File f1 = new File("E:\\test.jpg");
//2.目标图片
File f2 = new File("E:\\test1.jpg");
//3.输入管
FileInputStream fis = new FileInputStream(f1);
//4.输出管
FileOutputStream fos = new FileOutputStream(f2);
//5.功能加强,在FileInputStream外面套一个管BufferedInputStream
BufferedInputStream bis = new BufferedInputStream(fis);
//6.功能加强,在FileOutputStream外面套一个管BufferedOutputStream
BufferedOutputStream bos = new BufferedOutputStream(fos);
//7.开始动作
byte[] b = new byte[1024 * 8];
int len = bis.read(b);
while (len != -1){
bos.write(b,0,len);
/* bos.flush(); 底层已经帮我们做了刷新缓冲区的操作,不用我们手动完成:底层调用flushBuffer()*/
len = bis.read(b);
}
//8.关闭流
// 倒着关
//如果处理流包裹着节点流,那么只要关闭高级流(处理流),那么里面的字节流(fos、fis)会随之被关闭。
bos.close();
bis.close();
/*fos.close();
fis.close();*/
}
}
比对非文本文件复制的三种方法的效率
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
System.out.println("复制完成的时间:"+(endTime-startTime)+"毫秒");
耗时:一个一个字节 > 缓冲字节数组 > 缓冲区
12.2.5 BufferedReader、BufferedWriter缓冲字符流
package com.liweixiao.io02;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/8
* @description:
*/
public class Test07 {
public static void main(String[] args) throws IOException {
//1.原文件
File f1 = new File("e:\\test.txt");
//2.目标文件
File f2 = new File("e:\\test1.txt");
//3.输入字符管
FileReader fr = new FileReader(f1);
//4.输出字符管
FileWriter fw = new FileWriter(f2);
//5.加强功能,套一个缓冲输入管
BufferedReader br = new BufferedReader(fr);
//6.加强功能,套一个缓冲输出管
BufferedWriter bw = new BufferedWriter(fw);
//7.复制操作
//方式1
/*int n = br.read();
while (n != -1){
bw.write(n);
n=br.read();
}*/
//方式2
/*char[] ch = new char[30];
int len = br.read(ch);
while (len != -1){
bw.write(ch,0,len);
len=br.read(ch);
}*/
//方式3
String str = br.readLine();//每次读取一行
while (str != null){
bw.write(str);
//在文本文件中应该再写出一个换行
bw.newLine();
str=br.readLine();
}
//8.关闭流
bw.close();
br.close();
}
}
12.2.6 InputStreamReader、OutpuStreamWriter转换流
作用:将字节流和字符流进行转换
属于字符流,通过后缀
InputStreamReader:字节输入流 -> 字符输入流
OutputStreamWriter:字符输出流 -> 字节输出流
package com.liweixiao.io03;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/8
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//1.原文件
File f1 = new File("e:\\test.txt");
//2.输入字节流
FileInputStream fis = new FileInputStream(f1);
//3.加入一个转换流,字节流转换为字符流
//将字节转换为字符的时候,需要指定一个编码,这个编码跟文件本身的编码格式统一
//如果编码格式不统一,出现乱码
//如果不写,获取程序本身的编码格式,已设置为utf-8
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//4.开始动作
char[] ch = new char[20];
int len = isr.read(ch);
while (len != -1){
//如果使用println,一行超过ch的长度将换行,所以此处使用print
System.out.print(new String(ch,0,len));
len=isr.read(ch);
}
//5.关闭流
isr.close();
fis.close();
}
}
【InputStreamReader、OutpuStreamWriter转换流实现文本文件的复制】
package com.liweixiao.io03;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/8
* @description:
*/
public class Test02 {
public static void main(String[] args) throws IOException {
//1.原文件
File f1 = new File("e:\\test.txt");
//2.目标文件
File f2 = new File("e:\\test1.txt");
//3.输入字节流FileInputStream
FileInputStream fis = new FileInputStream(f1);
//4.输出字节流FileOutputStream
FileOutputStream fos = new FileOutputStream(f2);
//5.转换输入流InputStreamReader
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//6.转换输出流OutputStreamWriter
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
//7.复制
char[] ch = new char[20];
int len = isr.read(ch);
while (len != -1){
osw.write(ch,0,len);
len=isr.read(ch);
}
//8.关闭流
osw.close();
isr.close();
}
}
12.4 System类对IO流的支持
【1】System的属性:
System.in:“标准”输入流 -> 默认情况下 从键盘输入
System.out:“标准”输出流 -> 默认情况下 输出到控制台
【2】System.in
package com.liweixiao.io04;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
/**
* @author:LiWeixiao
* @date:2023/2/8
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//得到一个标准输入流,从键盘输入
/*InputStream in = System.in;
//调用方法
int n = in.read();//read方法等待键盘的录入,所以这个方法是一个阻塞方法。
System.out.println(n);//输入a输出(ascii码)97*/
//案例,从键盘录入一个int类型的数据
//从上面代码证明,键盘录入实际是System.in
//形象的理解:System.in是一根管,怼到键盘上,从键盘上录入到程序中
//Scanner作用:扫描器,扫键盘从这根管出来的数据
/*Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.println(i);*/
//既然Scanner是扫描的作用,不一定非得扫System.in进来的数据,还可以扫描其它管的内容
Scanner sc = new Scanner(new FileInputStream(new File("e:\\test.txt")));
while (sc.hasNext()){
System.out.println(sc.next());
sc.hasNext();
}
}
}
【3】System.out
package com.liweixiao.io04;
import java.io.PrintStream;
/**
* @author:LiWeixiao
* @date:2023/2/8
* @description:
*/
public class Test02 {
public static void main(String[] args) {
//写到控制台
PrintStream out = System.out;
//调用方法
out.print("你好1");//直接在控制台写出,不换行
out.print("你好2");
out.println("你好3");//换行
out.println("你好4");
out.println("你好5");
System.out.println("你好6");
}
}
【键盘录入内容保存到文本】
以上图片来自网络
package com.liweixiao.io04;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test03 {
public static void main(String[] args) throws IOException {
//1.先准备输入方向
//键盘录入
InputStream is = System.in;
//字节流转换字符流
InputStreamReader isr = new InputStreamReader(is);
//输入缓冲流,增强功能
BufferedReader br = new BufferedReader(isr);
//2.输出方向
//目标文件
File f2 = new File("e:\\demo1.txt");
//输出字符流
FileWriter fw = new FileWriter(f2);
//输出缓冲流,增强功能
BufferedWriter bw = new BufferedWriter(fw);
//3.开始动作
String s = br.readLine();
//while (s != null){//这样写有问题
while (! s.equals("exit")){
bw.write(s);
bw.newLine();//文件中换行
s=br.readLine();
}
//4.关闭流
bw.close();
br.close();
}
}
12.2.7 DataInputStream、DataOutputStream数据流(不重要,了解即可)
【1】数据流:用来操作基本数据类型和字符串的
【2】
DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
DataOutputStream:将内存中的基本数据类型和字符串的变量 写出 文件中
【利用DataOutputStream向外写出变量】
package com.liweixiao.io05;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//DataOutputStream:将内存中基本类型和字符串的变量 写出 文件中
File f1 = new File("e:\\test.txt");
FileOutputStream fos = new FileOutputStream(f1);
DataOutputStream dos = new DataOutputStream(fos);
//new DataOutputStream(new FileOutputStream(new File("e:\\test.txt")));
//将变量写到文件中
dos.writeUTF("你好");
dos.writeBoolean(false);
dos.writeDouble(6.9);
//关闭流
dos.close();
}
}
写到文件中的是乱码,是给程序看的
【利用DataInputStream读取变量】
package com.liweixiao.io05;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test02 {
public static void main(String[] args) throws IOException {
//DataInputStream
DataInputStream dis = new DataInputStream(new FileInputStream(new File("e:\\test.txt")));
//将文件中内容读取到程序中
System.out.println(dis.readUTF());
System.out.println(dis.readBoolean());
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
//关闭流
dis.close();
}
}
12.2.8 ObjectInputStream、ObjectOutputStream对象流
【1】对象流ObjectInputStream、ObjectOutputStream
用于存储和读取基本数据类型数据或对象的处理流。
它的强大之处就是可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来。
【2】序列号和反序列化
ObjectOutputStream类:把内存中的Java对象转换成平台无关的二进制数据,从而允许把这种二进制数据持久保存在磁盘上,或通过网络将二进制数据传输到另一个网络节点。 -> 序列化
ObjectInputStream类:当其它程序获取了这种二进制数据,就可以恢复成原来的java对象。 -> 反序列化
【3.1将字符串写入到文件中,序列化】
package com.liweixiao.io06;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//将内存中的字符串写到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("e:\\test.txt")));
//字符串写出
oos.writeObject("你好");
//关闭流
oos.close();
}
}
查看文件,乱码,是给程序看的。
【3.2读取文本中字符串,反序列化】
package com.liweixiao.io06;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//将文件中保存的字符串 读入 内存:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("e:\\test.txt")));
//读取字符串
String s = (String) (ois.readObject());
System.out.println(s);
//关闭流
ois.close();
}
}
实现SeriaLizable接口
【4.1自定义类,序列化】
自定义类必须要实现一个接口,序列化
public interface Serializable {
}
接口内部,什么都没有,这种接口叫标识接口。
只要实现这个接口的类的对象才能序列化,否则不可以。
package com.liweixiao.io07;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Person implements java.io.Serializable{
private static final long serialVersionUID = -1178538688015123993L;
//private static final long serialVersionUID = 12345L;
//属性
private String name;//姓名
private int 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;
}
//构造器
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.liweixiao.io07;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test01 {
public static void main(String[] args) throws IOException {
//序列化:将内存中对象 写入 文件
//有一个对象
Person p = new Person("lili", 19);
//有对象流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("e:\\test2.txt")));
//向外写,序列化
oos.writeObject(p);
//关闭流
oos.close();
}
}
【4.2自定义类,反序列化】
package com.liweixiao.io07;
import java.io.*;
/**
* @author:LiWeixiao
* @date:2023/2/9
* @description:
*/
public class Test02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//将文件中保存的对象 读入 内存
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("e:\\test2.txt")));
//读取对象
Person p = (Person) (ois.readObject());
System.out.println(p);
//关闭流
ois.close();
}
}
serialVersionUID
凡是实现Serializable接口(标识接口)的类都有一个表示序列化版本标识符的静态常量:
➢private static final long serialVersionUID;
➢serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序加化时是否兼容。
➢如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明。
➢简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
【IDEA配置】
以上图片来自网络
在Person类上 alt+enter
【序列化细节】
(1)被序列化的类的内部的所有属性,必须是可序列化的 (基本数据类型都是可序列化的)。
(2)static,transient修饰的属性 不可以被序列化。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)