Java 笔记 22:java.io.File,序列化

Java 笔记 22

java.io.File:类

  • 文件和目录 路径名的抽象表示形式。
  • 通俗的讲:File类的对象代表一个文件或一个目录(文件夹)

1、路径的分隔符:

  • windows:\ 和 /
  • 其他平台:/
  • 网络地址:http://www.baidu.com/index.html
  • 现在写路径分隔符:(1)/(2)File.separator
	public void test01(){
		File ioBJ1 = new File("D:\\尚硅谷_190513班_柴林燕_JavaSE\\笔记\\后续笔记\\第14章 IO流.docx");
		File ioBJ2 = new File("D:/尚硅谷_190513班_柴林燕_JavaSE/笔记/后续笔记/第14章 IO流.docx");
		File ioBJ3 = new File("D:" +File.separator+ "尚硅谷_190513班_柴林燕_JavaSE" +File.separator+ "笔记" +File.separator+ "后续笔记" +File.separator+ "第14章 IO流.docx");
	
		File dir1 = new File("D:/尚硅谷_190513班_柴林燕_JavaSE/笔记/后续笔记");
	}

2、API

  • (1)获取文件或目录的详细信息
  • getName()
  • long length():只能返回文件的大小,不能直接返回目录的大小
  •  	文件夹的总大小 = 文件夹里面的所有的文件大小累加和
    
  • isHidden()
  • exist()
  • canRead()
  • canWrite()
    *long lastModified()
	public void test02(){
		File file = new File("D:/尚硅谷_190513班_柴林燕_JavaSE/笔记/后续笔记/第14章 IO流.docx");
		System.out.println("文件名:" + file.getName());
		System.out.println("文件大小:" + file.length() + "字节");
		System.out.println("文件是否是隐藏文件:" + file.isHidden());
		System.out.println("文件是否存在:" + file.exists());
		System.out.println("文件是否可读:" + file.canRead());
		System.out.println("文件是否可写:" + file.canWrite());
		
		String parent = file.getParent();//返回父目录的名称
		File dir = file.getParentFile();//返回父目录的File对象
		System.out.println("文件的父目录:" + parent);
		
		
		System.out.println("文件最后修改时间:" + file.lastModified()+"毫秒");
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("文件最后修改时间:" + sf.format(new Date(file.lastModified())));
	}

(2)获取文件或目录的路径

  • getPath()
  • getAbsolutePath()
  • getCanonicalPath()
	public void test03() throws IOException{
		//绝对路径:从根目录开始导航,就是绝对路径
		File file = new File("D:/尚硅谷_190513班_柴林燕_JavaSE/笔记/后续笔记/第14章 IO流.docx");
		System.out.println("文件的路径:" + file.getPath());
		System.out.println("文件的绝对路径:" + file.getAbsolutePath());
		System.out.println("文件的规范路径:" + file.getCanonicalPath());
	}
	public void test04() throws IOException{
		//相对路径:相对当前的项目
		File file = new File("后续笔记/第14章 IO流.docx");
		System.out.println("文件的路径:" + file.getPath());
		System.out.println("文件的绝对路径:" + file.getAbsolutePath());
		System.out.println("文件的规范路径:" + file.getCanonicalPath());
	}
	public void test05() throws IOException{
		//非规范路径:带../或./或/
		File file = new File("../../后续笔记/第14章 IO流.docx");
		System.out.println("文件的路径:" + file.getPath());
		System.out.println("文件的绝对路径:" + file.getAbsolutePath());
		System.out.println("文件的规范路径:" + file.getCanonicalPath());//会自动解析:../等


  • (3)创建、删除、重命名
  • createNewFile():只能创建文件
  • mkdir():只能创建一级目录
  • mkdirs():创建多级目录
  • delete():可以删除文件
  •  	可以删除空目录
    
  • renameTo(File dest):可以给文件或目录重命名
  • (4)判断是文件还是目录
  • isDirectory():是存在的一个文件夹,返回true
  • isFile():是存在的一个文件,返回true
  • (5)不存在的一个文件或目录
  • 你获取它的name,path这些是有值,因为这些属性是通过构造器创建File时指定的。
  • 而其他的属性都是默认值。
  • 数组:length属性
  • String:length()
  • 文件:length()
	public void test08() throws IOException{
		File file = new File("d:/IOTest/java/atguigu");
		if(!file.exists()){
			System.out.println("文件夹不存在,创建这个文件夹");
			file.mkdirs();
		}
	}
	
	
	@Test
	public void test07() throws IOException{
		File file = new File("d:/IOTest");
		if(!file.exists()){
			System.out.println("文件夹不存在,创建这个文件夹");
			file.mkdir();
		}
	}
	
	@Test
	public void test06() throws IOException{
		File file = new File("d:/1.txt");
		if(!file.exists()){
			System.out.println("文件不存在,创建这个文件");
			file.createNewFile();
		}
	}
	@Test
	public void test11() throws IOException{
		File file = new File("d:/IOTest/java");
		file.delete();
	}
	
	@Test
	public void test10() throws IOException{
		File file = new File("d:/IOTest/java/atguigu");
		file.delete();
	}
	
	
	@Test
	public void test09() throws IOException{
		File file = new File("d:/1.txt");
		file.delete();
	}

文件过滤器

文件或目录过滤器

  • File类中
  • File[] listFiles(FileFilter f)
	public void test01(){
		//列出D:\atguigu\javaee\JavaSE20190513\code\day01_code目录下的所有的.java文件
		File dir = new File("D:/atguigu/javaee/JavaSE20190513/code/day01_code");
		File[] listFiles = dir.listFiles(new FileFilter() {
			
			//File pathname表示dir这个目录的下一级的每一个文件或目录
			//这个方法返回true,说明要保留的
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".java");
			}
		});
		
		for (File file : listFiles) {
			System.out.println(file);
		}
	}
	
	@Test
	public void test02(){
		//列出D:\atguigu\javaee\JavaSE20190513\code\day01_code目录下的所有的.java文件
		//并源文件名中包含Test这个单词
		File dir = new File("D:/atguigu/javaee/JavaSE20190513/code/day01_code");
		File[] listFiles = dir.listFiles(new FileFilter() {
			
			//File pathname表示dir这个目录的下一级的每一个文件或目录
			//这个方法返回true,说明要保留的
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".java") && pathname.getName().contains("Test");
			}
		});
		
		for (File file : listFiles) {
			System.out.println(file);
		}
	}
	
	@Test
	public void test03(){
		//列出D:\atguigu\javaee\JavaSE20190513\code\day01_code目录下的所有的文件名的长度超过10个字符的
		File dir = new File("D:/atguigu/javaee/JavaSE20190513/code/day01_code");
		File[] listFiles = dir.listFiles(new FileFilter() {
			
			//File pathname表示dir这个目录的下一级的每一个文件或目录
			//这个方法返回true,说明要保留的
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().length()>10;
			}
		});
		
		for (File file : listFiles) {
			System.out.println(file);
		}
	}

IO

1、IO:

  • I:input,输入
  • O:output:输出
  • (1)如果对于File对象来说,输入和输出操作只能针对文件,不能针对目录。
  • (2)IO操作不仅仅是针对文件,它可以从网络中输入和输出…
  • (3)输入:
  • 输出:
  • 参照物是当前程序
  • 例如:把数据写到文件中:输出操作 把数据从程序中输出到文件
  •   从文件读取数据: 输入操作
    
  • 例如:
  •  服务器端发送数据给客户端:
    
  •  		对于服务器来说是输出
    
  •  		对于客户端来说是输入
    
  • 2、IO的分类
  • (1)方向
  • 输入流和输出流
  • (2)操作数据的单位
  • 字节流和字符流
  • 字节流:以字节为单位byte
  • 字符流:以字符为单位char
  • 字符流只能用于读/写纯文本数据
  • 纯文本数据:内容全部是字符
  • 纯文本文件:
  •  	.txt,.html,.xml,.properties等是纯文本文件
    
  •  	.doc,.xls,.ppt等都不是
    
  • 字节流适用于任何类型的文件。
  • 如果是纯文本文件用字符流快。
  • (3)功能角色不同
  • 节点流和处理流
  • 节点流:和某个节点关联,例如:文件流。。。
  • 处理流:在节点流的基础上,加其他的处理功能的,加装饰功能的,例如:缓冲流,序列化与反序列化等
  • 3、IO流有四大抽象的基类/超类/父类
  • (1)InputStream:字节输入流
  • (2)OutputStream:字节输出流
  • (3)Reader:字符输入流
  • (4)Writer:字符输出流
  • 例如:文件IO流
  • (1)FileInputStream:文件字节输入流
  • (2)FileOutputStream:文件字节输出流
  • (3)FileReader:文件字符输入流
  • (4)FileWriter:文件字符输出流
  • 例如:缓冲IO流
  • (1)BufferedInputStream:字节缓冲输入流
  • (2)BufferedOutputStream:字节缓冲输出流
  • (3)BufferedReader:字符缓冲输入流
  • (4)BufferedWriter:字符缓冲输出流

文件的IO操作:

  • Reader系列:
  • (1)int read() :读取一个字符,正常返回是该字符的Unicode编码值
  • (2)int read(char[] cbuf) :读取多个字符,读取的字符放到cbuf数组中,从cbuf的[0]开始存储,最多读取cbuf.length个
  •  实际本次读取的字符的个数
    
  • (3)int read(char[] cbuf, int off, int len) :读取多个字符,读取的字符放到cbuf数组中,从cbuf的[off]开始存储,最多读取len个
  •  实际本次读取的字符的个数
    
  • 如果流中没有数据可读,统统返回-1
  • 一、读取一个纯文本的文件
  • 步骤:
  • (1)选择IO流,创建IO对象
  • (2)读/写操作
  • (3)关闭IO流,释放资源
	public void test04() throws IOException{
		//1、选择IO流
		//因为是操作纯文本文件,所以这里选择字符流
		//因为是读取操作,所以选择字符输入流   FileReader
		FileReader fr = new FileReader("1.txt");//相对路径,相对于当前的项目
		
		//2、读取文件内容
		//数据流向: 1.txt --> fr流中 -->从流中开始读取
		char[] arr = new char[10];
		while(true){
			int len = fr.read(arr);
			if(len == -1){
				break;
			}
			System.out.print(new String(arr,0,len));
		}
		
		//3、关闭
		fr.close();
	}
	
	@Test
	public void test03() throws IOException{
		//1、选择IO流
		//因为是操作纯文本文件,所以这里选择字符流
		//因为是读取操作,所以选择字符输入流   FileReader
		FileReader fr = new FileReader("1.txt");//相对路径,相对于当前的项目
		
		//2、读取文件内容
		//数据流向: 1.txt --> fr流中 -->从流中开始读取
		char[] arr = new char[10];
		while(true){
			int len = fr.read(arr);
			if(len == -1){
				break;
			}
			System.out.println(new String(arr,0,len));
		}
		
		//3、关闭
		fr.close();
	}
	
	
	//IOException是FileNotFoundException的父类,都是编译时异常
	@Test
	public void test02() throws IOException{
		//1、选择IO流
		//因为是操作纯文本文件,所以这里选择字符流
		//因为是读取操作,所以选择字符输入流   FileReader
		FileReader fr = new FileReader("1.txt");//相对路径,相对于当前的项目
		
		//2、读取文件内容
		//数据流向: 1.txt --> fr流中 -->从流中开始读取
		char[] arr = new char[10];
		int len = fr.read(arr);
		System.out.println(len);
		
		//3、关闭
		fr.close();
	}
		
	
	//IOException是FileNotFoundException的父类,都是编译时异常
	@Test
	public void test01() throws IOException{
		//1、选择IO流
		//因为是操作纯文本文件,所以这里选择字符流
		//因为是读取操作,所以选择字符输入流   FileReader
		FileReader fr = new FileReader("1.txt");//相对路径,相对于当前的项目
		
		//2、读取文件内容
		//数据流向: 1.txt --> fr流中 -->从流中开始读取
		int data = fr.read();
		System.out.println(data);
		
		//3、关闭
		fr.close();
	}

Writer:

  • (1)void write(int c) :写单个字符
  • (2)void write(char[] cbuf) :把整个字符数组的内容都写出去
  • (3)void write(char[] cbuf, int off, int len) :把cbuf[off]开始,len个字符写出去
  • (4)void write(String str) :把str的内容都写出去
  • (5)void write(String str, int off, int len) :把str从[off]开始len个字符写出去
  • (6)void close() 关闭
  • (7)void flush() 刷新
  • 二、写一些数据到纯文本文件中
  • 步骤:
  • (1)选择IO流,并创建对象
  • (2)读/写
  • (3)关闭
public class TestFileWriter {
	@Test
	public void test02() throws IOException{
		Scanner input = new Scanner(System.in);
		System.out.print("请输入一句话:");
		String str = input.nextLine();
		
		//1、选择IO流,并创建对象
		FileWriter fw = new FileWriter("1.txt",true);
		
		//2、写数据
		fw.write("\n");
		fw.write(str);
		
		//3、关闭
		fw.close();
		input.close();
	}
	
	@Test
	public void test01() throws IOException{
		Scanner input = new Scanner(System.in);
		System.out.print("请输入一句话:");
		String str = input.nextLine();
		
		//1、选择IO流,并创建对象
		FileWriter fw = new FileWriter("1.txt");
		
		//2、写数据
		fw.write(str);
		
		//3、关闭
		fw.close();
		input.close();
	}
}

Scanner:

  • (1)next():遇到空白符就认为输入结束
  • (2)nextLine():遇到换行符认为输入结束
public class TestNextLine {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
//		String str = input.nextLine();
//		String str = input.next();
//		System.out.println(str);
		
		System.out.print("请输入整数:");
		int num = input.nextInt();
		System.out.print("请输入小数:");
		double d = input.nextDouble();
		input.nextLine();
		System.out.print("请输入字符串:");
		String str = input.nextLine();//读取上一个输入流中的换行符
//		String str = input.next();
		
		System.out.println(num);
		System.out.println(d);
		System.out.println(str);
	}
}

OutputStream:

  • (1)void write(int b) :写一个字节
  • (2)void write(byte[] b) :写一个字节数组的所有
  • (3)void write(byte[] b, int off, int len) :写一个字节数组的部分
  • (4) void close()
  • (5)void flush()
public class TestCopy {
	@Test
	public void test02() throws IOException{
		copy("单身狗.jpg", "2.jpg");
	}
	
	@Test
	public void test01() throws IOException{
		copy("1.txt", "3.txt");
		/*
		 * 这里没有乱码,把1.txt的所有字节,每十个一复制, 全部复制到3.txt中,然后一起显示,没有缺字节
		 * 而且1.txt和3.txt的编码是一致的
		 */
	}
	
	//复制任意类型的文件的功能
	//任意类型的文件,只能选择字节流
	public void copy(String srcFilename , String destFilename) throws IOException{
		FileInputStream fis = new FileInputStream(srcFilename);
		FileOutputStream fos = new FileOutputStream(destFilename);
		
		byte[] arr = new byte[10];
		int len;
		//数据: srcFilename --> fis --> arr --> fos --> destFilename
		while((len = fis.read(arr)) !=-1){
			fos.write(arr, 0, len);
		}
		
		fis.close();
		fos.close();
	}
}

InputStream:

  • (1)int read() :一次读取一个字节,返回本次读取的字节的值
  • (2)int read(byte[] b) :一次读取多个字节,返回本次实际读取字节数,读取的字节存到b数组中,从[0]开始存储,一次最多读取b.length个字节
  • (3)int read(byte[] b, int off, int len) :一次读取多个字节,返回本次实际读取字节数,读取的字节存到b数组中,从[off]开始存储,一次最多读取len个字节
  • (4)close()
  • 如果到达流末尾,返回-1
  • 三、使用字节流,来读取纯文本文件
  • 步骤:
  • (1)选择IO流
  • (2)读/写
  • (3)关闭
	public static void main(String[] args) throws IOException {
		//(1)选择IO流
		//这里故意选取字节流,因为字节流可以用于处理所有类型的问题
		FileInputStream fis = new FileInputStream("1.txt");
		
		//(2)读
		byte[] arr = new byte[10];
		int len;
		while((len = fis.read(arr)) != -1){
//			System.out.println(Arrays.toString(arr));
			
			//字节数组-->字符串  new String(byte[],off,len)
			System.out.println(new String(arr,0,len));//可能乱码
			//乱码的原因:本次读了10个字节,就用10个字节去组成字符串显示了,出现缺字节
		}
		
//		(3)关闭
		fis.close();
	}

缓冲IO流:

  • 是处理流,负责在其他IO流基础上增加缓冲功能。提高效率
  • BufferedReader —> Reader
  • BufferedWriter —> Writer
  • BufferedInputStream —> InputStream
  • BufferedOutputStream —> OutputStream
  • BufferedReader除了继承了Reader的那些读的方法,还增加了一个:String readLine()读取一行
  • BufferedWriter除了继承了Writer的那些写的方法,还增加了一个:void newLine()写换行符
  • 默认的缓冲区的大小:8192字节/字符
    先关外部的(buffer),再关内部的(fileR/W)
public class TestBuffered {
	@Test
	public void test01() throws IOException{
		//用它来读取一个文件,因为控制台只能显示文本数据,所以我们这里用纯文本文件来演示
		FileReader fr = new FileReader("1.txt");
		BufferedReader br = new BufferedReader(fr);
		
		//数据:1.txt --> fr --> br
		String str ;
		while((str = br.readLine()) != null){
			System.out.println(str);
		}
		
		br.close();
		fr.close();
	}
	
	@Test
	public void test02()throws IOException{
		long start = System.currentTimeMillis();
		FileReader fr = new FileReader("1.txt");
		BufferedReader br = new BufferedReader(fr);
		
		FileWriter fw = new FileWriter("11.txt");
		BufferedWriter bw = new BufferedWriter(fw);
		
		String str ;
		////数据:1.txt --> fr --> br --> str --> bw --> fw -- >11.txt
		while((str = br.readLine()) != null){
			bw.write(str);
			bw.newLine();//换行
		}
		
		bw.close();
		fw.close();
		br.close();
		fr.close();
		
		long end = System.currentTimeMillis();
		System.out.println("毫秒:" + (end-start));
	}
	
	
	@Test
	public void test03() throws IOException{
		long start = System.currentTimeMillis();
		copy("D:/software/IDEA/ideaIU-Ultimate-2017.1.4.exe","d:/idea.exe");
		long end = System.currentTimeMillis();
		System.out.println("毫秒:" + (end-start));
	}
	
	//复制任意类型的文件的功能
	//任意类型的文件,只能选择字节流
	public void copy(String srcFilename , String destFilename) throws IOException{
		FileInputStream fis = new FileInputStream(srcFilename);
		BufferedInputStream bis = new BufferedInputStream(fis);//fis比喻成内衣,bis是外套
		
		FileOutputStream fos = new FileOutputStream(destFilename);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		byte[] arr = new byte[10];
		int len;
		//数据: srcFilename --> fis --> arr --> fos --> destFilename
		while((len = bis.read(arr)) !=-1){
			bos.write(arr, 0, len);
		}
		
		bis.close();//先脱外套
		fis.close();//再脱内衣
		
		bos.close();
		fos.close();
	}
	
	@Test
	public void test05()throws IOException{
		FileWriter fw = new FileWriter("22.txt");
		fw.write("hello");
//		fw.write("\n");//控制台,notepad可以体现换行,但是记事本不可以,因为记事本是C写的,在C中换行是\r\n
		fw.write("\r\n");//\r本行结束,\n把光标移动到下一行
		fw.write("world");
		fw.close();
	}
}

解码: 字节输入流转字符输入流的转换流,同时还能指定编码方式

  • InputStreamReader:
public class TestInputStreamReader {
	@Test
	public void test03()throws IOException{
		//解码:字节-->字符
		FileInputStream fis = new FileInputStream("d:/io.txt");
		InputStreamReader isr = new InputStreamReader(fis,"GBK");//将fis流中的字节流按照GBK进行解码为字符流
		//数据:d:/io.txt(GBK)-->fis(纯字节)-->isr(GBK)解成字符流-->按字符读取
		char[] arr = new char[3];
		int len = isr.read(arr);
		System.out.println(new String(arr,0,len));
		
		isr.close();
		fis.close();
	}
	
	@Test
	public void test02() throws IOException{
		//String:解码
		//解码:字节-->字符
		FileInputStream fis = new FileInputStream("d:/io.txt");
		byte[] arr = new byte[10];
		int len = fis.read(arr);
		//String(byte[] bytes, String charsetName)
		//String(byte[] bytes, int offset, int length, String charsetName)
		System.out.println(new String(arr,0,len,"GBK"));
		fis.close();
	}
	
	@Test
	public void test01() throws IOException{
		//乱码:d:/io.txt的编码是GBK,平台是UTF-8
		FileReader fr = new FileReader("d:/io.txt");
		char[] arr = new char[1024];
		int len = fr.read(arr);
		System.out.println(new String(arr,0,len));
		fr.close();
	}
}

编码:字符–》字节

  • 把字符流转为字节流的转换流
  • OutputStreamWriter:
  •  把字符流转为字节流,并且可以指定编码
    
public class TestOutputStreamWriter {
	@Test
	public void test03()throws IOException{
		//当前平台是UTF-8,文件是GBK
		//String:编码的方法  getBytes()
		//编码:字符--》字节
		String str = "柴老师永远18岁!永远美丽";
		FileOutputStream fos = new FileOutputStream("d:/io.txt");
		OutputStreamWriter oos = new OutputStreamWriter(fos, "GBK");
		
		oos.write(str);//数据:  str(字符)-->oos(字符)按照GBK编码为字节流-->fos --> io.txt
		
		oos.close();
		fos.close();
	}
	
	
	@Test
	public void test02()throws IOException{
		//当前平台是UTF-8,文件是GBK
		//String:编码的方法  getBytes()
		//编码:字符--》字节
		String str = "柴老师永远18岁!";
		FileOutputStream fos = new FileOutputStream("d:/io.txt");
		fos.write(str.getBytes("GBK"));
		fos.close();
	}
	
	
	@Test
	public void test01()throws IOException{
		//当前平台是UTF-8,文件是GBK
		String str = "柴老师永远18岁!";
		
		FileWriter fw = new FileWriter("d:/io.txt");
		fw.write(str);
		fw.close();
	}
}

程序中有这样一组数据:

  • int num = 10;
  • char c = ‘好’;
  • double d = 88.88;
  • String info = “尚硅谷真好!”;
  • boolean good = true;
  • 程序运行过程中,想要临时退出,下次希望从这个状态继续恢复执行。
  • 希望Java能够输出各种数据类型的数据,读取时,能还原各种数据类型的数据。
  • 因为这些数据不是纯文本,那么只能选择字节流。
  • Java中IO流的类的体系设计,隐含了一个设计模式:装饰者设计模式
  • DataOutputStream在OutputStream的基础上,增加了很多方法:
  • writeXxx(…)
  • DataInputStream在InputStream的基础尚自,增加了很多方法:
  • Xxx readXxx()
  • 要求:
  • 用DataOutputStream写的文件或数据,得用DataInputStream来读取。
  • 并且要求读的顺序与写的顺序要一致。
public class TestData {
	@Test
	public void test02()throws IOException{
		FileInputStream fis = new FileInputStream("data.dat");
		DataInputStream dis = new DataInputStream(fis);
		
		int num = dis.readInt();
		char c = dis.readChar();
		double d = dis.readDouble();
		String s = dis.readUTF();
		boolean b = dis.readBoolean();
		
		System.out.println(num);
		System.out.println(c);
		System.out.println(d);
		System.out.println(s);
		System.out.println(b);
		
		dis.close();
		fis.close();
	}
	
	@Test
	public void test01()throws IOException{
		int num = 10;
		char c = '好';
		double d = 188.88;
		String info = "尚硅谷真好!";
		boolean good = true;
		 
		FileOutputStream fos = new FileOutputStream("data.dat");
		/*fos.write(num);//错误的
		fos.write(c);
		fos.write((byte)d);*/
		DataOutputStream dos = new DataOutputStream(fos);
		
		dos.writeInt(num);
		dos.writeChar(c);
		dos.writeDouble(d);
		dos.writeUTF(info);
		dos.writeBoolean(good);
		
		dos.close();
		fos.close();
	}
}

序列:排队,

  • 把对象转为字节序列,序列化的过程
  • ObjectOutputStream:用于输出对象,把对象转成字节数据输出,对象的输出过程称为序列化。
  •  ObjectOutputStream比OutputStream多了很多方法,其中一个是  writeObject(obj)
    
  • 只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
    writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。
  • ObjectInputstream:用于输入对象,把字节序列转为对象读取,对象的读取过程称为反序列化。
  •  ObjectInputstream比InputStream多了很多方法,其中一个是 Object readObject()
    
public class TestObject {
	@Test
	public void test02()throws IOException, ClassNotFoundException{
		FileInputStream fis = new FileInputStream("obj.dat");
		ObjectInputStream ois = new ObjectInputStream(fis);
		Object obj = ois.readObject();
		//把字节流中的数据,转为一个对象,读取过程中会创建对象,new对象时需要找对象的类型
		System.out.println(obj);
		
		ois.close();
		fis.close();
	}
	
	@Test
	public void test01()throws IOException{
		User u = new User("chailinyan","123456",28);
		
		FileOutputStream fos = new FileOutputStream("obj.dat");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		//数据:程序-->oos --> fos -->obj.dat
		oos.writeObject(u);
		/*
		 * 如果没有实现Serializable接口的类型,在序列化时,报错误NotSerializableException,不能序列化。
		 * 如果要解决问题,User类需要实现java.io.Serializable接口
		 */
		
		oos.close();
		fos.close();
	}
}

自定义异常时:

  • (1)继承Throwable或它的子类
  • 一般是Exception和RuntimeException比较多
  • (2)建议保留两个构造器,一个无参,一个可以message赋值的构造器
  • (3)建议增加serialVersionUID
public class TestException {

}
class MyException extends Exception{

	private static final long serialVersionUID = 1L;

	public MyException() {
		super();
		
	}

	public MyException(String message) {
		super(message);
		
	}
	
}

需求:

  • 不是对象中的所有属性都需要序列化的。
  • 如果某个属性不需要序列化,可以在属性的前面加一个关键字:transient 。
  • 如果某个属性是static,那么也不会序列化。因为静态的变量不属于某个对象,而是整个类的,所以不需要随着对象的序列化而序列化。

在序列化Husband对象,要求Wife序列化。

  • 这里发现String类型也实现序列化接口了。
  • 结论:
  • 序列化一个对象时,要求它的属性要么是基本数据类型,如果是引用数据类型,这个引用数据类型也必须实现Serializable接口。
  • 序列化一个数组,要求元素类型实现Serializable接口。

猜你喜欢

转载自blog.csdn.net/qq_40473204/article/details/107691503