IO流
一,IO流的理解
i : input 输入
o:output 输入
流:方式,传递数据的方式---------相当于生活中的“管道”,“车”,将资源从一个位置,传递到另一个位置
二,IO流的分类
根据流的方向:输入流,输出流
根据流处理信息的大小: 字节流byte,字符流char
根据流的功能:节点流,处理流
-
IO流体系结构
三,使用流对象
- 获得数据源对象:
- 获得流对象同时链接数据源
- 读取数据: ,---隐式打开水龙头
- 关闭!
举个例子: 水资源,水管,====>打开水龙头,利用水管,来浇花!
四,File类
-
在java程序中操纵 文件/目录 ?怎么办?
-
java程序,最典型的特点,面向对象,java程序最擅长的就是操作对象,盘符上的文件/目录,将它的各种信息进行了封装,封装为一个对象,
-
java程序最擅长的就是操纵对象,这个对象属于 ---》File类
-
读取文件/对文件进行操作
public static void main1(String[] args) throws IOException { //1.获得数据源对象: File file=new File("E:\\dz15\\1.txt"); //2.获得流对象,同时连接数据源: Reader fr=new FileReader(file); //3.读取: int number = fr.read(); while(number!=-1){ System.out.print((char)number); number=fr.read(); } //4.关闭: fr.close(); } //========================================================================================= public class Test01 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //将文件封装为一个File类的对象: File f = new File("d:\\test.txt"); File f1 = new File("d:\\test.txt"); File f2 = new File("d:/test.txt"); //File.separator属性帮我们获取当前操作系统的路径拼接符号 //在windows,dos下,系统默认用“\”作为路径分隔符 ,在unix,url中,使用“/”作为路径分隔符。 File f3 = new File("d:"+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()); System.out.println("----------------------"); File f5 = new File("demo.txt"); if(!f5.exists()){ f5.createNewFile(); } //绝对路径指的就是:真实的一个精准的,完整的路径 System.out.println("绝对路径:"+f5.getAbsolutePath()); //相对路径:有一个参照物,相对这个参照物的路径。 //在main方法中,相对位置指的就是:D:\IDEA_workspace\TestJavaSE //在junit的测试方法中,相对路径指的就是模块位置 System.out.println("相对路径:"+f5.getPath()); //toString的效果永远是 相对路径 System.out.println("toString:"+f5.toString()); File f6 = new File("a/b/c/demo.txt"); if(!f5.exists()){ f5.createNewFile(); } System.out.println("绝对路径:"+f6.getAbsolutePath()); System.out.println("相对路径:"+f6.getPath()); }
-
图片复制
public static void main(String[] args) throws IOException { //1.获得数据源对象: File ifile= new File("D:\\1.png"); File ofile=new File("E:\\1.png"); //2.获得流对象同时连接数据源: InputStream is=new FileInputStream(ifile); OutputStream os=new FileOutputStream(ofile); //3.读取 同时 写入: byte[] bys=new byte[1024*8]; int i=is.read(bys); int count=0; while(i!=-1){ System.out.println("写入"+(++count)); os.write(bys); i=is.read(bys); } //4.关闭: 先开的后关: os.close(); is.close(); System.out.println("复制完成!"); }
-
对目录进行操作
public class Test02 { //这是一个main方法,是程序的入口: public static void main(String[] args) { //将目录封装为File类的对象: File f = new File("D:\\IDEA_workspace"); 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("D:\\a\\b\\c");【特殊强调,该目录不可以是隐藏目录!不然获得的file为null】 //创建目录: //f2.mkdir();//创建单层目录 //f2.mkdirs();//创建多层目录 //删除:如果是删除目录的话,只会删除一层,并且前提:这层目录是空的,里面没有内容,如果内容就不会被删除 f2.delete(); //查看: 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()); } }
例题:其实就是获取d:/ccjrjava文件夹及其子文件夹下的所有.java文件,使用readLine()读取其中每一行,每读取一行,行数加1。所有的文件读取完毕,得到总共已经写的Java代码行数。需要结合递归实现
package ZongJie; import sun.reflect.generics.tree.VoidDescriptor; import java.io.*; public class Ccjrjava { private int count;//本类下调用 //统计一个java文件的行数 public void method2(File f1) throws IOException { //管道 FileReader fr=new FileReader(f1); BufferedReader br=new BufferedReader(fr); while (br.readLine() != null){//判断每一行是否为空 count++; } br.close(); } //统计文件夹中有多少Java文件 public void method1(String str) throws IOException { //获取数据源 File f1=new File(str); //判断是否存在 if (!f1.exists()||!f1.isDirectory()){ System.out.println("目录不存在"); return; } //查看目录 File[] f2 = f1.listFiles();//作用更加广泛 for (int i = 0; i < f2.length; i++) { if (f2[i].isFile()){//判断是否是一个文件 if(f2[i].getName().toLowerCase().endsWith(".java")){ //判断文件名全转为小写后,尾部是不是”.java“ method2(f2[i]);//转至method2去判断文件内部 } } //递归统计代码行数 if (f2[i].isDirectory()){ //准备统计的文件夹 String ss=f1+"\\\\"+f2[i].getName(); //得到文件夹后,再次重复判断其中的内容 method1(str); } } } public static void main(String[] args) throws IOException { //创建对象 Ccjrjava ccjrjava=new Ccjrjava(); ccjrjava.method1("D:\\dz\\ccjrjava"); System.out.println(ccjrjava.count); } }
五,IO应用
-
案例:通过JAVA完成文件的复制操作
- 功能分解1:文件--》程序:FileReader-----一个字符一个字符的将文件中的内容读取到程序中了:
public class Test01 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //文件--》程序: //1.有一个文件:----》创建一个File类的对象 File f = new File("d:\\Test.txt"); //2.利用FileReader这个流,这个“管”怼到源文件上去 ---》创建一个FileReader的流的对象 FileReader fr = new FileReader(f); //3.进行操作“吸”的动作 ---》读取动作 /*下面的代码我们验证了:如果到了文件的结尾处,那么读取的内容为-1 int n1 = fr.read(); int n2 = fr.read(); int n3 = fr.read(); int n4 = fr.read(); int n5 = fr.read(); int n6 = fr.read(); System.out.println(n1); System.out.println(n2); System.out.println(n3); System.out.println(n4); System.out.println(n5); System.out.println(n6);*/ //方式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((char)n); } //4.“管”不用了,就要关闭 ---》关闭流 //流,数据库,网络资源,靠jvm本身没有办法帮我们关闭,此时必须程序员手动关闭: fr.close(); }
- 功能分解2:程序--》文件:FileWriter-----一个字符一个字符的向外输出
public class Test03 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //1.有个目标文件: File f = new File("d:\\demo.txt"); //2.FileWriter管怼到文件上去: FileWriter fw = new FileWriter(f); //3.开始动作:输出动作: //一个字符一个字符的往外输出: String str = "hello你好"; for (int i = 0 ;i < str.length();i++){ fw.write(str.charAt(i)); } //4.关闭流: fw.close(); } }
- 功能分解3:利用FileReader,FileWriter文件复制
public class Test04 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //1.有一个源文件 File f1 = new File("d:\\Test.txt"); //2.有一个目标文件: File f2 = new File("d:\\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); 【】【写入一行内容同时换行 fw.write("123456"+"\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:利用缓冲字符数组,将数组转为String写出。 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(); } }
-
利用try-catch-finally处理异常方式
public class Test04 { //这是一个main方法,是程序的入口: public static void main(String[] args) { //1.有一个源文件 File f1 = new File("d:\\Test.txt"); //2.有一个目标文件: File f2 = new File("d:\\Demo.txt"); //3.搞一个输入的管 怼到源文件上: FileReader fr = null; FileWriter fw = null; try { fr = new FileReader(f1); //4.搞一个输出的管,怼到目标文件上: fw = new FileWriter(f2); //5.开始动作: 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) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //6.关闭流:(关闭流的时候,倒着关闭,后用先关) try { if(fw!=null){//防止空指针异常 fw.close(); } } catch (IOException e) { e.printStackTrace(); } try { if(fr!=null){ fr.close(); } } catch (IOException e) { e.printStackTrace(); } }
-
FileInputStream读取文件中内容
- 读取文本文件:
public class Test01 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //功能:利用字节流将文件中内容读到程序中来: //1.有一个源文件: File f = new File("D:\\Test.txt"); //2.将一个字节流这个管 怼 到 源文件上: FileInputStream fis = new FileInputStream(f); //3.开始读取动作 /* 细节1: 文件是utf-8进行存储的,所以英文字符 底层实际占用1个字节 但是中文字符,底层实际占用3个字节。 细节2: 如果文件是文本文件,那么就不要使用字节流读取了,建议使用字符流。 细节3: read()读取一个字节,但是你有没有发现返回值是 int类型,而不是byte类型? read方法底层做了处理,让返回的数据都是“正数” 就是为了避免如果字节返回的是-1的话,那到底是读入的字节,还是到文件结尾呢。 */ int n = fis.read(); while(n!=-1){ System.out.println(n); n = fis.read(); } //4.关闭流: fis.close(); } }
- 利用字节流读取非文本文件:(以图片为案例:)--》一个字节一个字节的读取:
public class Test02 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //功能:利用字节流将文件中内容读到程序中来: //1.有一个源文件: File f = new File("D:\\LOL.jpg"); //2.将一个字节流这个管 怼 到 源文件上: FileInputStream fis = new FileInputStream(f); //3.开始读取动作 int count = 0;//定义一个计数器,用来计读入的字节的个数 int n = fis.read(); while(n!=-1){ count++; System.out.println(n); n = fis.read(); } System.out.println("count="+count); //4.关闭流: fis.close(); } }
- 利用字节类型的缓冲数组:
public class Test03 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //功能:利用字节流将文件中内容读到程序中来: //1.有一个源文件: File f = new File("D:\\LOL.jpg"); //2.将一个字节流这个管 怼 到 源文件上: FileInputStream fis = new FileInputStream(f); //3.开始读取动作 //利用缓冲数组:(快递员的小车) byte[] b = new byte[1024*6]; int len = fis.read(b);//len指的就是读取的数组中的有效长度 while(len!=-1){ //System.out.println(len); for(int i = 0;i<len;i++){ System.out.println(b[i]); } len = fis.read(b); } //4.关闭流: fis.close(); } }
-
FileInputStream,FileOutputStream完成非文本文件的复制
-
读入一个字节,写出一个字节:
public class Test04 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //功能:完成图片的复制: //1.有一个源图片 File f1 = new File("d:\\LOL.jpg"); //2.有一个目标图片: File f2 = new File("d:\\LOL2.jpg"); //3.有一个输入的管道 怼 到 源文件: FileInputStream fis = new FileInputStream(f1); //4.有一个输出的管道 怼到 目标文件上: FileOutputStream fos = new FileOutputStream(f2); //5.开始复制:(边读边写) int n = fis.read(); while(n!=-1){ fos.write(n); n = fis.read(); } //6.关闭流:(倒着关闭流,先用后关) fos.close(); fis.close(); } }
- 利用缓冲字节数组:
public class Test05 { //这是一个main方法,是程序的入口: public static void main(String[] args) throws IOException { //功能:完成图片的复制: //1.有一个源图片 File f1 = new File("d:\\LOL.jpg"); //2.有一个目标图片: File f2 = new File("d:\\LOL2.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); len = fis.read(b); } //6.关闭流:(倒着关闭流,先用后关) fos.close(); fis.close(); } }
-
缓冲字节流(处理流)-BufferedInputStream ,BufferedOutputStream
public class Test06 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//1.有一个源图片
File f1 = new File("d:\\LOL.jpg");
//2.有一个目标图片:
File f2 = new File("d:\\LOL2.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*6];
int len = bis.read(b);
while(len!=-1){
bos.write(b,0,len);
/* bos.flush(); 底层已经帮我们做了刷新缓冲区的操作,不用我们手动完成:底层调用flushBuffer()*/
len = bis.read(b);
}
//8.关闭流:
//倒着关:
//如果处理流包裹着节点流的话,那么其实只要关闭高级流(处理流),那么里面的字节流也会随之被关闭。
bos.close();
bis.close();
/*fos.close();
fis.close();*/
}
}
-
比对非文本文件复制的三种方法的效率
public class Test06 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//1.有一个源图片
File f1 = new File("d:\\LOL.jpg");
//2.有一个目标图片:
File f2 = new File("d:\\LOL2.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.开始动作 :
long startTime = System.currentTimeMillis();
byte[] b = new byte[1024];
int len = bis.read(b);
while(len!=-1){
bos.write(b,0,len);
/* bos.flush(); 底层已经帮我们做了刷新缓冲区的操作,不用我们手动完成:底层调用flushBuffer()*/
len = bis.read(b);
}
long endTime = System.currentTimeMillis();
System.out.println("复制完成的时间为:"+(endTime-startTime));
//8.关闭流:
//倒着关:
//如果处理流包裹着节点流的话,那么其实只要关闭高级流(处理流),那么里面的字节流也会随之被关闭。
bos.close();
bis.close();
/*fos.close();
fis.close();*/
}
}
-
缓冲字符流(处理流)-BufferedReader,BufferedWriter完成文本文件的复制
public class Test07 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//1.有一个源文件:
File f1 = new File("d:\\Test.txt");
//2.有一个目标文件:
File f2 = new File("d:\\Demo.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:
String str = br.readLine();//每次读取文本文件中一行,返回字符串
while(str!=null){
bw.write(str);
//在文本文件中应该再写出一个换行:
bw.newLine();//新起一行
str = br.readLine();
}
//8.关闭流
bw.close();
br.close();
}
}
-
转换流-InputStreamReader,OutputStreamWriter
public class Test01 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//文件---》程序:
//1.有一个源文件:
File f = new File("d:\\Test.txt");
//2.需要一个输入的字节流接触文件:
FileInputStream fis = new FileInputStream(f);
//3.加入一个转换流,将字节流转换为字符流:(转换流属于一个处理流)
//将字节转换为字符的时候,需要指定一个编码,这个编码跟文件本身的编码格式统一
//如果编码格式不统一的话,那么在控制台上展示的效果就会出现乱码
//InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//获取程序本身的编码--》utf-8
InputStreamReader isr = new InputStreamReader(fis);
//4.开始动作,将文件中内容显示在控制台:
char[] ch = new char[20];
int len = isr.read(ch);
while(len!=-1){
//将缓冲数组转为字符串在控制台上打印出来
System.out.print(new String(ch,0,len));
len = isr.read(ch);
}
//5.关闭流:
isr.close();
}
}
-
转换流-InputStreamReader,OutputStreamWriter实现文本文件的复制
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//1.有一个源文件
File f1 = new File("d:\\Test.txt");
//2.有一个目标文件:
File f2 = new File("d:\\Demo.txt");
//3.输入方向:
FileInputStream fis = new FileInputStream(f1);
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//4.输出方向:
FileOutputStream fos = new FileOutputStream(f2);
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
//5.开始动作:
char[] ch = new char[20];
int len = isr.read(ch);
while(len!=-1){
osw.write(ch,0,len);
len = isr.read(ch);
}
//6.关闭流:
osw.close();
isr.close();
}
}
-
System类对IO流的支持
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//写到控制台:
PrintStream out = System.out;
//调用方法:
out.print("你好1");//直接在控制台写出,但是不换行
out.print("你好2");
out.print("你好3");
out.print("你好4");
out.println("我是中国人1");//直接在控制台写出,并且换行操作
out.println("我是中国人2");
out.println("我是中国人3");
out.println("我是中国人4");
System.out.println("你是");
System.out.print("中国人");
}
}
-
练习:键盘录入内容输出到文件中
public class Test03 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//1.先准备输入方向:
//键盘录入:
InputStream in = System.in;//属于字节流
//字节流--》字符流:
InputStreamReader isr = new InputStreamReader(in);
//在isr外面再套一个缓冲流:
BufferedReader br = new BufferedReader(isr);
//2.再准备输出方向:
//准备目标文件
File f = new File("d:\\Demo1.txt");
FileWriter fw = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(fw);
//3.开始动作:
String s = br.readLine();
while(!s.equals("exit")){
bw.write(s);
bw.newLine();//文件中换行
s = br.readLine();
}
//4.关闭流:
bw.close();
br.close();
}
}
-
数据流-DataInputStream,DataOutputStream
数据流:用来操作基本数据类型和字符串
DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
DataOutputStream: 将内存中的基本数据类型和字符串的变量 写出 文件中
//输出
public class Test01 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//DataOutputStream: 将内存中的基本数据类型和字符串的变量 写出 文件中
/*File f = new File("d:\\Demo2.txt");
FileOutputStream fos = new FileOutputStream(f);
DataOutputStream dos = new DataOutputStream(fos);*/
DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("d:\\Demo2.txt")));
//向外将变量写到文件中去:
dos.writeUTF("你好");
dos.writeBoolean(false);
dos.writeDouble(6.9);
dos.writeInt(82);
//关闭流:
dos.close();
}
}
//输入
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
DataInputStream dis = new DataInputStream(new FileInputStream(new File("d:\\Demo2.txt")));
//将文件中内容读取到程序中来:
System.out.println(dis.readUTF());
System.out.println(dis.readBoolean());
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
//关闭流:
dis.close();
}
}
-
对象流-ObjectInputStream,ObjectOutputStream
1.对象流:ObjectInputStream,ObjectOnputStream
用于存储和读取基本数据类型数据或对象的处理流。
它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
2.序列化和反序列化:
(1)ObjectOutputStream 类 : 把内存中的Java对象转换成平台无关的二进制数据,从而允许把这种二进制数据持久地保存在磁盘上,或通过网络将这种二进制数据传输到另一个网络节点。----》序列化
细节:
被序列化的类的内部的所有属性,必须是可序列化的 (基本数据类型都是可序列化的)
static,transient修饰的属性 不可以被序列化。
public class Person implements Serializable { private static final long serialVersionUID = 8027651838638826533L; private transient String name; private static int age; private Famaily f = new Famaily(); 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() { } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", f=" + f + ",age=" + age + '}'; } }
public class Test01 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:\\Demo3.txt")));
//将内存中的字符串写出到文件中:
oos.writeObject("你好");
//关闭流:
oos.close();
}
}
(2) 用ObjectInputStream类 : 当其它程序获取了这种二进制数据,就可以恢复成原来的Java对象。----》反序列化
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException, ClassNotFoundException {
//将文件中保存的字符串 读入到 内存:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:\\Demo3.txt")));
//读取:
String s = (String)(ois.readObject());
System.out.println(s);
//关闭流:
ois.close();
}
}
3.操作自定义类的对象
4 序列号:.serialVersionUID
alt+enter: 回车 即可生成序列号
自定义类
public class Person implements Serializable {
private static final long serialVersionUID = 8027651838638826533L;
private transient String name;
private static int age;
private Famaily f = new Famaily();
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() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", f=" + f + ",age=" + age +
'}';
}
}
测试类
public class Test01 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//序列化:将内存中对象 ---》 文件:
//有一个对象:
Person p = new Person("lili",19);
//有对象流:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:\\Demo4.txt")));
//向外写:
oos.writeObject(p);
//关闭流:
oos.close();
}
}
反序列化
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:\\Demo4.txt")));
//读入内存:
Person p = (Person)(ois.readObject());
System.out.println(p/*.toString()*/);
//关闭流:
ois.close();
}
}
文本文件:.txt .java .c .cpp ---》建议使用字符流操作
非文本文件:.jpg, .mp3 , .mp4 , .doc , .ppt ---》建议使用字节流操作