Javo IO专题

Java IO 专题  

一、编码问题

从联通.txt和联.txt显示不正常,进而找到编码问题。
0xff 就是16进制数,前面全是0,后8位全为1。

import java.io.UnsupportedEncodingException;
public class EncodeDemo  {
	public static void main(String[] args) throws UnsupportedEncodingException
	{
		String s = "慕课ABC";
		//获得本地默认的编码
		byte[] bytes1 = s.getBytes();
		for(byte b : bytes1){
			//把字节转换成int,以16进制的方式显示
			System.out.print(Integer.toHexString(b & 0xff)+"  ");
		}
		System.out.println();
		//转换成gbk编码
		byte[] bytes2 = s.getBytes("gbk");
		//gbk编码中文占用2个字节,英文占用1个字节
		for(byte b : bytes2){
			System.out.print(Integer.toHexString(b & 0xff)+"  ");
		}
		System.out.println();
		//utf-8 中,中文占3个字节,英文占1个字节,一个字节8bit
		byte[] bytes3 = s.getBytes("utf-8");
		for(byte b : bytes3){
			System.out.print(Integer.toHexString(b & 0xff)+"  ");
		}
		//
		System.out.println();
		byte[] byte5 = new byte[]{(byte) 01110111,(byte) 11100101};
		String str0 = new String(byte5,"utf-16be");
		System.out.println(str0);
		//ystem.out.println(Integer.toHexString(0xa1+0xa2+0xb4+0xff),"GBK");
		//java是双字节编码 utf-16be
		//utf-16be 中文占用两个字节,英文也是占用两个字节
		byte[] bytes4 = s.getBytes("utf-16be");
		for(byte b : bytes4){
			System.out.print(Integer.toHexString(b&0xff)+"  ");
		}
		System.out.println();
		/*
		 * 当你的字节序列是某种编码时,这个时候想把字节序列变成
		 * 字符串,也需要用这种编码方式,否则会出现乱码
		 */
		String str1 = new String(bytes4);//用项目默认的编码
		System.out.println(str1);
		String str2 = new String(bytes4,"unicode");
		System.out.println(str2);//使用java的双字节编码,utf-16be
		System.out.println(s);
		/*
		 * 文本文件 就是字节序列
		 * 可以是任意编码的字节序列
		 * 如果我们在中文机器上直接创建文本文件,那么该文本文件只认识ANSI编码,别的不认识,但是文本文件本身可以放任何编码
		 * 联通,联  这是一种巧合,他们正好符合了utf-8编码的规则。纯属巧合
		 * 直接粘贴过来的都认识 
		 * 什么编码项目认识什么样的东西  如果复制内容过去,会自动做转换。
		 */
	}
}

输出如下:



二、File类的使用

注意:java.io.File类用于表示文件(目录)

File类只用于表示文件(目录)的信息(名称,大小等),不能用于进行文件的访问。

package com.Imooc;
import java.io.File;
import java.io.IOException;
public class FileDemo {
	public static void main(String[] args){
		//了解构造函数的情况,查帮助   alt+/
		//   ctrl+ // 得到的是注释这行
		File file = new File("E:\\kankan\\联通.txt");
		System.out.println(file.exists());
		if(!file.exists())
			file.mkdir();//file.mkdirs() 创建多级目录
		else
			file.delete();
		//是否是一个目录,如果是目录返回true,不是或不存在,返回false
		System.out.println(file.isDirectory());
		//是否是一个文件
		System.out.println(file.isFile());
		
		File file2 = new File("E:\\kankan\\1.txt");
		if(!file2.exists())
			try {
				file2.createNewFile();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		else
			file2.delete();
		//常用的File对象的API
		System.out.println(file);//直接打印file.toString()内容,打印出来的是文件String名
		System.out.println(file.getName()+" 的绝对路径为::"+file.getAbsolutePath());
		System.out.println(file.getName());
		System.out.println(file2.getName());
		System.out.println(file.getParent());
		System.out.println(file2.getParent());
		System.out.println(file2.getParentFile());
		System.out.println(file.getParentFile().getAbsolutePath());
		System.out.println(file.getParentFile().getName());	
	}
}


System.out.println();快捷键,syso+Alt+/ 。 下面的程序,用来展示list的用法

先写一个类,用来写测试函数:

    下面方法中的递归,直接把函数再一次加进去,这样就达到了无限次的递归的原理,这样可以统计一个文件夹里共有多少个文件。

package com.Imooc;
import java.io.*;
//功能,列出File的一些常用操作,比如过滤,遍历目录等操作,包装成一个工具类
public class FileUtils {
	/*
	 * 列出指定目录下(包括其子目录)的所有文件
	 */
	public static void listDirectory(File dir) throws IOException
	{
		if(!dir.exists()){
			//写一半可以使用alt+/获取帮助
			throw new IllegalArgumentException("目录"+dir+"不存在");
		}
		if(!dir.isDirectory()){
			throw new IllegalArgumentException(dir+"不是目录");
		}
		/*
		//foreach出名字  list()返回一个String数组
		String[] filenames = dir.list();//list()方法用于列出当前目录下的子目录和文件,返回字符串数组,直接子的名称,不包含子目录下的内容
		for(String filename : filenames){
			System.out.println(dir+"\\"+filename);
		}
		*/
		//需要增加判断。拿到文件名,再构造成一个File对象,递归遍历下面的内容。File提供了直接返回File对象的API
		File[] files = dir.listFiles();//返回的直接子目录(文件)的抽象
		if(files!=null && files.length>0){
			for(File file:files){
				if(file.isDirectory()){
					//递归
					listDirectory(file);
				}else{
					System.out.println(file);
				}
			}
		}
/*		for(File filename : files){//foreach语句
			if(filename.isDirectory()){
				//对下面的文件继续递归
				listDirectory(filename);//方法嵌套
			}
			else
				System.out.println(filename);
		}*/
	}
}
给一段加注释,①加//这样的注释,选中按“Ctrl+/”。②加/*   */ 这样的注释,按“Shift+Ctrl+/”。

下面再写一个测试类:

package com.Imooc;
import java.io.*;
public class FileUtilTest1 {
	public static void main(String[] args) throws IOException  {
		FileUtils.listDirectory(new File("E:\\java\\codes\\12"));
	}
}
这样就把 “E:\java\codes\12”下的所有文件(包括子目录里的文件)全部列出

三、RandomAccessFile

RandomeAccessFile java提供的对文件内容的访问,即可以读文件,也可以写文件。RandomeAccessFile支持随机访问文件,可以访问文件的任意位置。

1、java文件模型

在硬盘上的文件是byte byte byte存储的,是数据的集合

2、打开文件
两种模式“”“rw”(读写),“r”(只读)
RandomeAccessFile raf = new RandomeAccessFile(file,"rw")
因为是随机访问文件,所以会包含一个文件指针,打开文件时,指针在开头,pointer=0; 这个指针会移动。
3、写方法
raf.write(int) ---> 只写一个字节(后8位),同时指针指向下一个位置。
4、读方法:
int b = raf.read() ---> 读一个文件,从指针出开始
5、file.close();
文件读写完后以后一定要关闭(否则会有意想不到的错误)
下面写一个类,完成的功能就是打开文件,然后RandomeAccessFile进行读写操作。
里面的0x7fffffff是int最大的,01111111111111111111111111111111,首位0是符号位,表示是正数。很多方法都可以边学编写。不用把所有的API都看一遍。
package com.Imooc;
import java.io.*;
import java.util.Arrays;
public class RafDemo  {
	public static void main(String[] args) throws IOException{
		File file1 = new File(".");
		System.out.println(file1.getAbsolutePath());
		File demo = new File("demo");
		if(!demo.exists())
			demo.mkdir();
		File file = new File(demo,"raf.dat");
		if(!file.exists())//不存在就创建
			file.createNewFile();
		RandomAccessFile raf = new RandomAccessFile(file,"rw");
		//查看指针位置
		System.out.println(raf.getFilePointer());
		raf.write('A');//写一个字节,写入后八位,也有可能后八位代表
		System.out.println(raf.getFilePointer());//输出1
		raf.write('B');
		System.out.println(raf.getFilePointer());//输出2
		int i = 0x7fffffff;//一个字节是8位,一共四个字节
		//用write方法每次只能写一个字节,如果要把i写进去就得写4次
		raf.write(i>>>24);
		raf.write(i>>>16);
		raf.write(i>>>8);
		raf.write(i);
		System.out.println(raf.getFilePointer());//输出6
		//可以直接写一个int进去
		raf.writeInt(i);//又写了4个
		System.out.println(raf.getFilePointer());//输出10
		String s = "吕泽正";//6个字节
		byte[] gbk = s.getBytes("gbk");
		raf.write(gbk);
		System.out.println("现在文件中内容长度为(按照字节数来说):"+raf.length());
		//读文件,必须把指针移动到头部
		raf.seek(0);///移动到10的时候,他能正确读到 吕泽正 这个字
		//一次性读取,吧文件中的内容都读到字节数组中
		byte[] buf = new byte[(int)raf.length()];
		raf.read(buf);//方法read(byte[] buf) 读取到buf数组中去
		System.out.println(raf.getFilePointer());//这就读取到16位了
		System.out.println(Arrays.toString(buf));
		String s1 = new String(buf);
		System.out.println(s1+"  ");
		for(byte b : buf)
		{
			System.out.print(Integer.toHexString(b & 0xff)+"  ");
		}
		raf.close();//记得关闭
	}
}

IO流,Java做输入输出的基础,分为输入流/输出流。又分为字节流,字符流。可以以字节为单位,可以以字符为单位。

四、字节流

两个抽象父类

1、InputStream、OutputStream

InputStream抽象了应用程序读取数据的方式
OutputStream抽象了应用程序写出数据的方式。

2、EOF = End 读到-1就读到结尾了。

重要方法:

3、输入流:基本方法主要是读

int b = in.read(); 读取一个字节, 无符号填充到int的低8位,高8位补零。读到-1 EOF结束。
in.read(byte[] buf) 读取数据填充到字节数组buf
int.read(byte[] buf,int start,int size)。读取数据到字节数组buf。从buf的start位置开始,存放size长度的数据
4、输出基本方法
out.write(int b); 写出一个byte到流 ,b的低8位。
out.write(byte[] buf); 将buf字节数组都写入到流
out.write(byte[] buf,int start,int size);字节数组buff从start位置开始,写size长度的字节到流。

5、FileInputStream子类 继承勒InputStream  ----> 具体实现了在文件上读取数据

package com.Imooc;
import java.io.*;
public class IOUtil {
	/*
	 * 读取指定文件内容,按照16进制输出到控制台
	 * 并且每输出10byte字节,我们就换行
	 */
	public static void printHex(String fileName) throws IOException{//调用的时候传入
		//把文件作为字节流进行读操作
		FileInputStream in = new FileInputStream(fileName);
		int b;//4个字节。
		int i=1;
		while((b=in.read())!=-1){//如何读,如何读到结束,其实b的值每次都刷新
			//in.read():读取一个字节,一个字节是8bit
			if(b<=0xf){
				//单位数前面补0
				System.out.print("0");
			}
			//toHexString是进制转换
			System.out.print(Integer.toHexString(b)+"  ");//将整型b转换为16进制表示的字符串
			if(i++%10==0){
				System.out.println();
			}
		}
		in.close();
	}
	public static void printHexByByteArray(String fileName) throws IOException{
		FileInputStream in = new FileInputStream(fileName);
		byte[] buf = new byte[1];
		//从in这个文件中批量读取字节,放到buf这个字节数组中,
		//从第0个位置开始放,最多放buf.length个,
		//返回的是独到的字节的个数
		/*int bytes  = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大,这里返回的就是字节长度。所以下面是 i<bytes。
		int j=1;
		for(int i=0;i<bytes;i++){
			if(buf[i]<=0xf){
				System.out.print(0);
			}
			System.out.print(Integer.toHexString(buf[i])+" ");
			if(j++%10==0)
				System.out.println();
		}*/
		int bytes = 0;
		int j=1;
		while((bytes = in.read(buf,0,buf.length))>=0){
			for(int i = 0;i< buf.length;i++){
				if(buf[i]<0xf){
					System.out.print("0");
				}
				System.out.print(Integer.toHexString(buf[i] & 0xff)+"  ");
				//byte类型为8位,int类型为32位,为了避免数据转换错误,通过&0xff将高24位清零
				if(j++%10 == 0){
					System.out.println();
				}
			}
		}
		in.close();
	}
	//写一个文件复制的程序 利用读操作和写操作,字节批量读取,直接字节数组
	public static void copyFile(File srcFile,File desFile) throws IOException{
		if(!srcFile.exists()){//文件不存在不行
			throw new IllegalArgumentException("文件:"+srcFile+"不存在!");
		}
		if(!srcFile.isFile()){//不是文件不行
			throw new IllegalArgumentException(srcFile+"不是文件");
		}
		FileInputStream in = new FileInputStream(srcFile);
		FileOutputStream out = new FileOutputStream(desFile);
		byte[] buf = new byte[1024];//这里的大小很重要,大的话才是整体输入
		int b;
		while ((b=in.read(buf,0,buf.length))>0){
			out.write(buf, 0, b);
			out.flush();//最好加上
		}
		//关闭文件
		in.close();
		out.close();
	}
	/*
	 * 使用带缓冲的字节流,进行文件的拷贝
	 */
	public static void copyFileByBuffer(File srcFile,File destFile) throws IOException{
		if(!srcFile.exists()){//文件不存在不行
			throw new IllegalArgumentException("文件:"+srcFile+"不存在!");
		}
		if(!srcFile.isFile()){//不是文件不行
			throw new IllegalArgumentException(srcFile+"不是文件");
		}
		BufferedInputStream bis = new BufferedInputStream(
				new FileInputStream(srcFile));//参数必须是字节流,不能使文件,就是要包装成字节流。
		//FileInputStream是节点字节流,必须跟物理节点相连接。
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(destFile));
		int c;
		while((c = bis.read())!=-1){
			bos.write(c);
			bos.flush();//刷新缓冲区,必须
		}
		bis.close();
		bos.close();
	}
	/*
	 * 单字节不带缓冲进行文件拷贝
	 */
	public static void copyFileByByte(File srcFile,File destFile)throws IOException{
		if(!srcFile.exists()){//文件不存在不行
			throw new IllegalArgumentException("文件:"+srcFile+"不存在!");
		}
		if(!srcFile.isFile()){    //不是文件不行
			throw new IllegalArgumentException(srcFile+"不是文件");
		}
		FileInputStream in = new FileInputStream(srcFile);
		FileOutputStream out = new FileOutputStream(destFile);
		int c;
		while((c=in.read())!=-1)
		{
			out.write(c);
			out.flush();//缓冲的必须要flush
		}
		in.close();
		out.close();
	}
}


下面写一个测试类:

package com.Imooc;
import java.io.*;
public class IOUtilTest1 {
	public static void main(String[] args)throws IOException{
		//IOUtil.printHex("E:\\workspace\\com.Imooc\\Telphone.java");
		System.out.println();
		System.out.println("===================================");
		//IOUtil.printHexByByteArray("E:\\workspace\\com.Imooc\\Telphone.java");
		long s =System.currentTimeMillis();
		IOUtil.copyFile(new File("E:\\workspace\\com.Imooc\\Telphone.java"),
				new File("E:\\workspace\\com.Imooc\\CopyTelphone.java"));
		long start1 = System.currentTimeMillis();
		IOUtil.copyFileByBuffer(new File("E:\\workspace\\com.Imooc\\Telphone.java"),
				new File("E:\\workspace\\com.Imooc\\BufferedCopyTelphone.java"));
		long end1_start2 = System.currentTimeMillis();
		IOUtil.copyFileByByte(new File("E:\\workspace\\com.Imooc\\Telphone.java"), 
				new File("E:\\workspace\\com.Imooc\\SingleCopyTelphone.java"));
		long end2 = System.currentTimeMillis();
		System.out.println("-------------------------------------------");
		System.out.println(start1-s);
		System.out.println(end1_start2-start1);
		System.out.println(end2-end1_start2);//测试时间
	}
}



输出结果:

这是注释掉的部分,必须 byte[] buf = new byte[1024],足够大,才行,因为是一次性读取


这是用下面方法的输出。

6、FileOutputStream 实现了向文件中写入byte数据的方法

package com.Imooc;
import java.io.*;
public class FileOutDemo1 {
	public static void main(String[] args)throws IOException{
		//如果该文件不存在,则直接创建,如果存在,删除后创建
		FileOutputStream out = new FileOutputStream("demo/out.dat");
		//new FileOutputStream("demo/out.dat",true);//如果这样的话,就是追加,不会删除后创建了
		out.write('A');//写出A字符的低8位
		out.write('B');//写出B的低八位
		int a = 10;//write只能写8位,那么写一个整数需要写4次,每次8位
		out.write(a>>>24);
		out.write(a>>>16);
		out.write(a>>>8);
		out.write(a);
		byte[] gbk="中国".getBytes("gbk");
		out.write(gbk);
		out.close();
		IOUtil.printHex("demo/out.dat");//调用前面的,将写入的内容输出到控制台
	}
}
输出:
41 A 42 B 00 00 00 0a 10   因为整型是4字节,32位。写四次  d6 

7、DataOutputStream/DataInputStream

对流功能的扩展,可以更加方便读取int long,字符,等类型数据。主要操作类型数据。
DataOutputStream
writeInt()/writeDouble()/writeUTF()/
package com.Imooc;
import java.io.*;
public class DosDemo {
	public static void main(String[] args)throws IOException{
		String file = "demo/dos.dat";
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
		//用fileOutputSream的方法,写几次
		dos.writeInt(10);//执行了4次write()
		dos.writeInt(-10);
		dos.writeLong(10l);
		dos.writeDouble(10.5);
		//采用UTF-8编码写出
		dos.writeUTF("中国");
		//采用utf-16be编码写
		dos.writeChars("中国");
		dos.close();
		IOUtil.printHex(file);
	}
}

package com.Imooc;
import java.io.*;
public class DisDemo {
	public static void main(String[] args)throws IOException{
		String file = "demo/dos.dat";
		IOUtil.printHex(file);
		DataInputStream dis = new DataInputStream(new FileInputStream(file));
		int i = dis.readInt();//读取了4次 long是8次
		System.out.println(i);
		i=dis.readInt();
		System.out.println(i);
		long l = dis.readLong();
		System.out.println(l);
		double d = dis.readDouble();
		System.out.println(d);
		String s =  dis.readUTF();
		System.out.println(s);
	}
}

8、 BufferedInputStream&BufferedOutputStream


这两个流泪为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。
从应用程序中输入放入文件,相当于将一缸水倒入另一缸水中:
FileOutputStream ---->write()方法  相当于一滴一滴的把水转移过去。
DataOutputStream ----->writeXxx()方法会方便一些。一下写4个字节、8个  相当于一瓢一瓢的转移
BufferedOutputStream---->write()方法更方便,相当于一瓢一瓢水先放入桶中(缓存区),再从桶倒入到另一个缸中。

五、字符流

1、编码问题要清楚

2、认识文本和文本文件

Java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)
文件是byte byte byte .....的数据序列
文本文件是文本(char)序列按照某种编码方法(utf-8,uft-16be,gbk)序列化为byte的存储结果

3、字符流(Reader Writer)------>操作的是文本 文本文件

字符的处理,一次处理一个字符

字符的底层仍然是基本的字节序列。

字符流的基本实现

InputStreamReader 完成byte流解析为char流,按照编码解析

OutputStreamWriter 提供char流到byte流,按照编码存储

package com.Imooc;
import java.io.*;
public class IsrAndOswDemo {
	public static void main(String[] args) throws IOException
	{
		FileInputStream in = new FileInputStream("E:\\workspace\\com.Imooc\\imoocutf-8");
		InputStreamReader isr = new InputStreamReader(in,"utf-8");//这里默认是gbk,可以省略
		FileOutputStream out = new FileOutputStream("E:\\workspace\\com.Imooc\\imoocutf-81.txt");
		OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
		/*int c;
		while((c=isr.read())!=-1){
			System.out.print((char)c);
		}*/
		char[] buffer = new char[8];
		int c;
		//批量读取,放入buffer这个字符数组,从第0个位置开始防止,最多放buffer.length
		while((c = isr.read(buffer,0,buffer.length))!=-1){
			//System.out.print(c);
			//System.out.println("-----");
			String s = new String(buffer,0,c);
			System.out.print(s);
			osw.write(buffer,0,c);
			osw.flush();
		}
		isr.close();
		osw.close();
	}
}

4、FileReader 和 FileWriter   

可以不用上上面的InputStreamReader 这样的嵌套,直接可以写文件地址,直接对物理资源操作。

package com.Imooc;
import java.io.*;
public class FrAndFwDemo {
	public static void main(String[] args) throws IOException{
//		FileInputStream in = new FileInputStream("E:\\workspace\\com.Imooc\\imoocutf-8");
//		InputStreamReader ins = new InputStreamReader(in,"utf-8");
//		FileReader fr1 = new FileReader(new InputStreamReader(new FileInputStream("")));
		//File in = new File("E:\\workspace\\com.Imooc\\imoocutf-8.txt");
		FileReader fr = new FileReader("E:\\workspace\\com.Imooc\\imoocutf-8.txt");//没有放编码格式的例如“gbk”
		FileWriter fw = new FileWriter("E:\\workspace\\com.Imooc\\imoocutf1-8.txt");//如果名字一样的话,这样会删掉原来的东西
		//FileWriter fw = new FileWriter("E:\\workspace\\com.Imooc\\imoocutf-8.txt",true);//追加内容,带个true。
		char[] buffer = new char[1];
		int c;
		while((c=fr.read(buffer, 0, buffer.length))!=-1){
			//System.out.println("+++++++++++");
			System.out.print(new String(buffer,0,c));
			fw.write(buffer,0,c);
			fw.flush();
		}
		fr.close();
		fw.close();
	}
}

5、字符流可以加过滤,具备更强大的功能。

BufferedReader ----> readLine 一次读一行 

BufferedWriter/(结合)PrintWriter ----> writeLine 一次写一行


		FileReader fr = new FileReader("E:\\workspace\\com.Imooc\\imoocutf-8.txt");
		BufferedReader br = new BufferedReader(fr); 等同于下面
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
				"E:\\workspace\\com.Imooc\\imoocutf-8.txt")));

package com.Imooc;
import java.io.*;
public class BrAndBwOrPwDemo {
	public static void main(String[] args)throws IOException{
		//对文件进行读写操作
//		FileReader fr = new FileReader("E:\\workspace\\com.Imooc\\imoocutf-8.txt");
//		BufferedReader br = new BufferedReader(fr); 等同于下面
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
				"E:\\workspace\\com.Imooc\\imoocutf-8.txt")));
		/*BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
				"E:\\workspace\\com.Imooc\\bwutf-8")));*/
		FileWriter pw2 = new FileWriter("E:\\workspace\\com.Imooc\\bwut");
		//PrintWriter pw = new PrintWriter("E:\\workspace\\com.Imooc\\bwutf-8");
		PrintWriter pw1 = new PrintWriter(pw2,true);//自动刷新
		
		String line;
		while((line = br.readLine())!=null){
			System.out.println(line);//一次读一行,并不能识别换行,所以写为println 而不是print
			pw1.println(line);
			/*bw.write(line);
			//不认识换行,单独写出胡按行操作
			bw.newLine();
			bw.flush();*/
			/*pw.println(line);//换行方便
			pw.flush();*/
		}
		br.close();
		pw2.close();
		//bw.close();
		//pw.close();
	}
}

六、对象的序列化和反序列化

1、对象序列化:将Object转换成byte序列,反之叫对象的反序列化。
2、序列化流(ObjectOutputStream),是过滤流  ----writeObject
反序列化(ObjectInputStream) ------readObject 
3、序列化接口(Serializable)
对象必须实现序列化接口,才能进行序列化,否则将出现异常。
这个接口,没有任何方法,只是一个标准。
private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException
private void readObject(java.io.ObjectInputStream s)throws java.io.IOException,ClassNotFoundException
package com.Imooc;
import java.io.Serializable;
import java.util.ArrayList;
public class Student implements Serializable {
	private String studo;//String类实现了Serializable
	private String stuname;
	private transient int stuage;//该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化
	//ArrayList a = new ArrayList();
	public Student(){}
	public Student(String studo,String stuname,int stuage){
		super();//直接通过成员变量,生成构造方法
		this.studo = studo;
		this.stuname = stuname;
		this.stuage = stuage;
	}
	public String getStudo(){
		return studo;
	}
	public void setStudo(String studo){
		this.studo = studo;
	}
	public String getStuname(){
		return stuname;
	}
	public void setStuname(String stuname){
		this.stuname = stuname;
	}
	public int getStuage(){
		return stuage;
	}
	public void setStuage(int stuage){
		this.stuage = stuage;
	}
	public String toString(){
		return "Student[stuno="+studo+",stuname="+stuname+",stuage="+stuage+"]";
	}
	private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException
	{
		s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作
		s.writeInt(stuage);//自己完成stuage的序列化
	}
	private void readObject(java.io.ObjectInputStream s)throws java.io.IOException,ClassNotFoundException{
		s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作
		this.stuage = s.readInt();//自己完成stuage的反序列化操作
	}//用这个又能看到了
}


package com.Imooc;
import java.io.*;
public class ObjectSeriaDemo1 {
	public static void main(String[] args)throws IOException, ClassNotFoundException{
		//对象序列化就是把对象进行一个保存
		String file = "E:/"
				+ "workspace/com.Imooc/obj.dat";//把这个对象存在路径下
		//1、对象的序列化
		/*ObjectOutputStream oos = new ObjectOutputStream(
				new FileOutputStream(file));
		Student stu = new Student("10001","张三",20);//吧student对象保存起来
		oos.writeObject(stu);
		oos.flush();
		oos.close();*/
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
		Student stu =(Student)ois.readObject();//读出来的都是Ibjectr,所以强制类型转换
		System.out.println(stu);
		ois.close();//打印出来,说明对对象进行了存储
	}
}
4、分析ArrayList源码中序列化和反序列化的问题。  里面有一个  private transient Object[] elementData;
因为ArrayList不一定放满元素,序列化可以提高利用率。只是对有限元素做序列化。transient修饰,提高性能。将来自己做序列化的优化问题。
5、序列化中  子类和父类 构造函数的调用问题
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被显示调用。
package com.Imooc;

import java.io.*;

public class ObjectSeriaDemo2 {
	public static void main(String[] args) throws IOException, ClassNotFoundException{
		/*ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\workspace\\com.Imooc\\imoocutf-8"));
		Foo2 foo2 = new Foo2();//序列化完成了
		oos.writeObject(foo2);
		oos.flush();
		oos.close();*/
		//反序列化是否递归调用父类的构造函数
		/*ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\workspace\\com.Imooc\\imoocutf-8"));
		Foo2 foo2 = (Foo2)ois.readObject();
		System.out.println(foo2);
		ois.close();*/
		
		/*ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\workspace\\com.Imooc\\imoocutf-8"));
		Bar2 bar2 = new Bar2();//序列化完成了
		oos.writeObject(bar2);
		oos.flush();
		oos.close();*/
		
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\workspace\\com.Imooc\\imoocutf-8"));
		Bar bar2 = (Bar2)ois.readObject();
		System.out.println(bar2);
		ois.close();//这里表示父类构造函数被调用了  因为没有实现Implements调用了
		/*
		 * 对子类对象进行反序列化操作时,
		 * 如果其父类没有实现序列化接口,
		 * 那么其父类的构造函数会被显示调用。实现的接口及其子类不会调用。
		 */
	}
}
class Foo implements Serializable{
	//一个类实现了序列化接口,那么其子类都可以进行序列化
	public Foo(){
		System.out.println("foo...");
	}
}
class Foo1 extends Foo{
	public Foo1(){
		System.out.println("foo1...");
	}
}
class Foo2 extends Foo1{
	public Foo2(){
		System.out.println("foo2...");
	}
}
class Bar{
	public Bar(){
		System.out.println("Bar");
	}
}
class Bar1 extends Bar{// implements Serializable{
	public Bar1(){
		System.out.println("bar1...");
	}
}
class Bar2 extends Bar1 implements Serializable{
	public Bar2(){
		System.out.println("bar2...");
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值