java IO 字节流、字符流操作总结

8.0 java IO输入输出流

1.gbk 编码中文占用2个字节,英文占用1个字节。

2、utf-8编码中文占用3个字节,英文占用1个字节。

 

Java是双字节编码,utf-16be编码。即char占用2个字节。

注意:当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式。否则会出现乱码。

 

文本文件就是字节序列,可以是任意编码的字节序列。但是如果我们在中文的机器上直接创建文件,那么该文件只认识ANSI编码。

 

 

8.1 File类常用的API介绍

Java.IO.File类用于表示文件(目录)

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

常用的API

booleanexists();判断文件是否存在

创建File对象:File file=new File(String path);这里path就是文件的绝对位置,如:c:\\file\\dooc 或者c:/file/dooc.txt都可以。

file.mkdir();创建目录

file.isDirectory();测试此抽象路径名表示的文件是否是一个目录。

file.isfile();测试此抽象路径名表示的文件是否是一个文件。

file.delete();删除这个文件或者目录

file.creatNewFile();创建新文件

file.getName();获取文件名或者目录的名称

file.getAbsolutepath();获取绝对路径

file.getParent();获取父级路径,如果没有则返回null

String[] list();返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

File[] listfiles();返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

 

       File类中的list()方法用于列出当前的目录下的子目录和文件,返回的是字符串数组。直接列出子目录的文件,但不包含子目录的文件内容。

代码如下:

//实现一个遍历File对象的指定文件目录下的所有文件

public static void listDirectory(File dir) throws IOException{
		//判断dir目录存不存在
		try {
			if(dir.exists()){
				System.out.println("该目录存在");
			}else{
				throw new IllegalArgumentException("这个目录不存在");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		//判断目录下是否有文件
		try {
			if(dir.isDirectory()){
				System.out.println("该目录存在文件夹");
			}else{
				throw new IllegalArgumentException("该目录不存在文件");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		
		//方法一是调用list()方法来遍历,该方法返回的是一个字符串类型的数组
		//我们依次遍历看看看结果
//		String[] strs=dir.list();
//		//使用foreach语句来遍历
//		for (String string : strs) {
//			System.out.println(dir+"\\"+string);//加上根目录显示
//		}
//		
//		System.out.println("上面的方法只能显示到子文件类型,既不能显示具体"
//				+ "的文件名称,也不能显示子文件下的文件");
		System.out.println("");
		//下面调用listFile()方法,该方法返回的是File对象的数组。同时可以直接获取file下的所有文件
		File[] files=dir.listFiles();
		if(files!=null && files.length>0){//获取的数组即不为空,也不为0长度数组
			for (File file : files) {
				
				if(file.isDirectory()){//查看是否还有文件在下面
					listDirectory(file);//递归调用,直到没有子文件为止
				}
				else{
					System.out.println(file);
				}
			}
		}
	}

总结:创建工具类:FileUtil包装了一些File的常用操作,例如过滤和遍历等:

1、列出指定目录下的(包含子目录)的所有文件。

如果传进来的目录不存在或者不是文件夹,则应该抛出异常。这时我们需要用到判断语句。

2、如:file.list()方法;该方法返回当前目录下的文件名的字符串数组,但是不包含子目录下的文件和目录。

3、File[] files=file.listFile();可以直接获取file文件下的所有文件或者目录。然后以File对象数组的形式返回。然后可以调用递归就可以把所有的目录下的文件路径读出来,或者获取文件。代码如上。

 

8.2RandomAccessFile类介绍

   RandomAccessFile类对文件进行访问读写文件。随机访问文件即文件的任意的位置。

java文件模型在硬盘上的文件时byte byte byte存储的,是数据的集合。

打开文件

有2种模式可以打开文件:rw 读写模式和r只读模式

如:RandomAccessFile  raf=new RandomAccessFile(file,”rw”);

这里file的初始化如下:File file=new File(String path);

其中在读写文件时会有文件指针的存在,打开文件时文件的指针在开头,即pointer=0;

写方法

raf.write(int);当写一个int型数据时只写一个字节(即最后8位),同时文件指针pointer指向下一个位置准备再次写入:

读方法

//读取指定长度的字节内容

 raf.seek(0);//将文件指针指向最开始的头部

 byte[] buf=new byte[(int)raf.length()];

 raf.read(buf);//读取指定长度的字节内容,并将内容存储在buf数组中

 

   //读取一个字节

   raf.seek(0);//将文件指针指向最开始的头部

   int b=raf.read();//只读取一个字节

文件读写完毕后,一定要记得关闭文件

raf.close();

 

代码如下:

package com.ll.iofile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;

/**
 * 此方法用来测试RandomAccessFile类,用于读写文件
 * @author LULEI
 *
 */
public class testRandomAccessFile {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		
		File file=new File("Demo");//判断相对路径中是否存在指定的目录
		if(!file.exists()){
			file.mkdir();//新建一个Demo目录
		}
		File file2=new File(file,"wq.bat");//将指定的文件实例化给file2对象
		if(!file2.exists()){
			file2.createNewFile();//新建一个wq.bat文件
		}
		
		//创建一个从中读取和向里面写入的一个随机访问的文件流.该文件要有指定的名称
		RandomAccessFile raf=new RandomAccessFile(file2,"rw");//设置为读写模式
		//首先观察一下文件指针的位置
		System.out.println("文件指针的初始化位置在:"+raf.getFilePointer());
		
		//向文件流中进行写,注意一次只写一个字节
		raf.write('A');//注意char型字符占两个字节
		System.out.println("文件指针的位置在:"+raf.getFilePointer());
		String s="中";
		byte[] sTObyte=s.getBytes("gbk");//设置为国标
		raf.write(sTObyte);
		System.out.println("添加中文后的文件指针的位置:"+raf.getFilePointer());
		
		int iNum=89;
		raf.write(iNum>>>24);
		raf.write(iNum>>>16);
		raf.write(iNum>>>8);
		raf.write(iNum>>>0);
		System.out.println("普通方法添加int型数据后的文件指针的位置:"+raf.getFilePointer());
		byte[] bt={1,2,3,4};
		//可以写数组
		raf.write(bt);
		System.out.println("添加byte数组后的文件指针的位置:"+raf.getFilePointer());
		//可以直接写一个Int类型的数据
		raf.writeInt(20);//int占4个字节
		System.out.println("添加int型数据后的文件指针的位置:"+raf.getFilePointer());
		
		/*
		 * 向文件流进行读操作
		 */
		//一次只读一个字节的内容
		
		raf.seek(0);//读取数据之前一定要将文件指针指向头部
		int num=raf.read();
		System.out.println("只读一个字节返回的内容:"+Integer.toString(num));
		int num2=raf.read();
		System.out.println("只读一个字节返回的内容(十六进制显示):"+Integer.toHexString(num2&0xff));
		
		/*读取一定长度的字节的内容
		 * 读取文件前,一定要把文件指针指向开头
		 */
		raf.seek(0);
		int n=(int)raf.length();//获取文件流中内容的字节长度
		//创建一个同样长度大小的byte数组
		byte[] buf=new byte[n];
		raf.read(buf);//读取指定长度的字节内容,并将内容复制到buf数组中
		System.out.println("读取一定长度返回的内容");
		System.out.println(Arrays.toString(buf));
		for (byte b : buf) {
			System.out.print(Integer.toHexString(b & 0xff)+" ");
		}
		
		/*
		 * 最后关掉文件
		 */
		raf.close();
	}

}

8.3 字节流

1、IO流(输入流、输出流)

字节流

InputStream、OutputStream

InputStream抽象了应用程序读取数据的方式

OutputStream抽象了应用程序写出数据的方式

EOF=EndOf File,表示已经读完。读到-1时表示读到文件的结尾。

输入流基本的操作方法

int b=in.read();读一个字节,无符号填充到int低八位,-1表示EOF。

in.read(byte[]buf);读取数据填充到字节数组buf中

in.read(byte[]buf,int start,int size);读取数据到字节数组buf。然后从buf的start位置开始存放size长度的数据

输出流本操作

out.write(intb);写一个byte到流中,写的内容是b的低8位

out.write(byte[]buf);将一个buf字节数组都写入到流

out.write(byte[]buf,int start,int size);字节数组buf从start位置开始写size长度的字节到流。

 

 

 

2、FileInputStream 具体实现了文件上的读取文件

注:1>单字节的读取即不用数组,在读取大文件时效率较低。

       2>批量的读取,对于大文件而言效率较高,也是我们最常用的读取文件的方式。

       3>byte类型8位,int类型为32位,为了避免数据类型的转换的错误。通过0xff将高24为清零。

       4>read()适合单字节的读取大小

in.read(byte[] buf,int start,int size);字节数组适合读取大文件

 

 

3、FileOutputStream实现向文件中写出byte数据的方法。

文件输出流的写法:

   1>FileOutputStream  output=new FileOutputStream(file,true);//这个方法表示文件若不存在,则创建新的文件,若存在则在后面添加内容。

  2>FileOutputStream output=new FileOutputStream(file);//这个方法表示文件不存在就创建新文件,若文件存在则先删除文件然后再创建文件。

   3>在执行完output.write(byte[] buf,int start,int size)之后,一定要调用output.flush()方法来刷新。

 

 

代码如下:

package com.ll.iofile;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * 这个方法是用来测试字符流的
 * 主要用到是InputStreamReader 字符输出流
 * OutputStreamWriter 
 * @author LULEI
 *
 */
public class testInputStreamReaderAndOutputStreamWriter {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		/*这是测试第一个例子
		 * 就是将gbk编码的文件复制成utf-8格式的文件
		FileInputStream in=new FileInputStream("DEMO\\fileio1.txt");
		InputStreamReader isr=new InputStreamReader(in);//此处默认项目的编码是gbk的
		*/
		/*这是测试第一个例子
		 * 就是将gbk编码的文件复制成utf-8格式的文件
		FileOutputStream out=new FileOutputStream("Demo\\OutputStreamUTF8.txt");
		OutputStreamWriter osw=new OutputStreamWriter(out,"utf-8");
		*/
FileInputStream in=new FileInputStream("C:\\Users\\Administrator\\Desktop\\OutputStreamUTF8.txt");
		InputStreamReader isr=new InputStreamReader(in,"utf8");//这样的写法就是设置为utf8编码
		FileOutputStream out=new FileOutputStream("Demo\\OutputStreamGBK.txt");
		OutputStreamWriter osw=new OutputStreamWriter(out);//默认的编码就是gbk
		int c=0;
		/*这是单字节的输出
		while((c=isr.read())!=-1){
			System.out.print((char)c);
		}
		*/
		char[] buf=new char[20*1024];
		while((c=isr.read(buf, 0, buf.length))!=-1){
		//	String str=new String(buf);
		//	System.out.println(str);
			osw.write(buf,0,c);
			osw.flush();
		}
		isr.close();
		osw.close();
	}

}

8.4 数据输入输出流

它是字节流的一个拓展。它是用来帮助方便操作类型数据的。

1>  包含DataOutputStream和DataInputStream

2>  对“流“功能的扩展,可以更加方便的读取int,long,字符等类型数据。

3>  DataOutputStream的方法:

writeInt()/writeDouble()/writeUTF()

 

4>  DataInputStream的方法:

readInt()/readDouble()/readUTF()

代码如下:

package com.ll.iofile;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * 这个类用于测试数据的输入输出流
 * 即DataOutputStream 和DataInputStream
 * @author LULEI
 *
 */
public class testDataOutputStreamAndDataInputStream {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		//测试DataOutputStream类
		String str="Demo\\wq77.txt";
		DataOutputStream dos=new DataOutputStream(
				new FileOutputStream(str));//实例化一个对象
		dos.write(10);//占一个字节
		
		dos.writeInt(-10);//写一个int型整数,占4个字节
		dos.writeDouble(10.8);//占8个字节
		
		
		
		//以UTF-8的格式写入字符串
		dos.writeUTF("中国");//一个汉子占3个字节
		
		//以utf-16be的格式写入字符串
		dos.writeChars("中国");//一个汉字占2个字节
		
		dos.close();
		
		//打印输出的文件的字节
		IOUtils.printHexByByte(str);
		System.out.println();
		
		//实例化数据输入流对象
		DataInputStream dif=new DataInputStream(new FileInputStream(str));
		int a=dif.read();
		System.out.println(a);
		int b=dif.readInt();
		System.out.println(b);
		double d=dif.readDouble();
		System.out.println(d);
		
		String s1=dif.readUTF();
		System.out.println(s1);
		
		byte[] bytes=new byte[6];
		dif.read(bytes);
		System.out.println(Arrays.toString(bytes));//转换为字符串显示
		dif.close();
		
	}

}

8.4BufferedInputStream&BufferedOutputStream

这两个流位于IO提供了带有缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。从应用程序中把输入放入文件,相当于将一缸水倒入另一个缸中。

1>  FileOutputStream----》write方法相当于一滴一滴的把水转移过去。

2>  DataOutputStream--àwriteXXX方法会方便一些,相当于一瓢一瓢的把水转移过去

3>  BufferedOutputStreamàwrite()方法会更方便一些,相当于一瓢一瓢先放入水桶中,在从桶中倒入缸中,性能提高了。

 

代码如下:

package com.ll.iofile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 这个函数是为了测试BufferedOutputStream、FileOutputStream、DataOutputStream
 * 这三个类在copy文件时的速度快慢
 */
public class testBufferedOutputStreamAndBufferedInputStream {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		File file=new File("C:\\Users\\Administrator\\Desktop\\浪潮之巅.pdf");
		long start1=System.currentTimeMillis();
		FileToCopyByByte(file);
		long end1=System.currentTimeMillis();
		System.out.println(end1-start1);
		
		long start2=System.currentTimeMillis();
		FileToCopy(file);
		long end2=System.currentTimeMillis();
		System.out.println(end2-start2);
		
		long start3=System.currentTimeMillis();
		DataToCopy(file);
		long end3=System.currentTimeMillis();
		System.out.println(end3-start3);
		
		long start4=System.currentTimeMillis();
		bufferedFileToCopy(file);
		long end4=System.currentTimeMillis();
		System.out.println(end4-start4);
	}
	
	public static void FileToCopyByByte(File file)throws IOException{
		if(!file.exists()){
			System.out.println("文件"+file+"不存在");
		}
		if(!file.isFile()){
			System.out.println("文件"+file+"不是文件");
		}
		FileInputStream fis=new FileInputStream(file);//实例化读取字节的文件流
		//实例化写字节文件流
		FileOutputStream fos =new FileOutputStream("Demo\\fileIoByByte1.pdf");
		int b=0;
		while((b=fis.read())!=-1){
			fos.write(b);
		}
		fis.close();
		fos.close();
	}
	
	
	
	public static void FileToCopy(File file)throws IOException{
		if(!file.exists()){
			System.out.println("文件"+file+"不存在");
		}
		if(!file.isFile()){
			System.out.println("文件"+file+"不是文件");
		}
		FileInputStream fis=new FileInputStream(file);//实例化读取字节的文件流
		//实例化写字节文件流
		FileOutputStream fos =new FileOutputStream("Demo\\fileio1.pdf");
		 int length=0;
		 byte[] buf=new byte[20*1024]; 
		 while((length=fis.read(buf, 0, buf.length))!=-1){
			 fos.write(buf);
			// fos.flush();
		 }
		fis.close();
		fos.close();
	}
	
	
	
	public static void DataToCopy(File dateFile)throws IOException{
		if(!dateFile.exists()){
			System.out.println("文件"+dateFile+"不存在");
		}
		if(!dateFile.isFile()){
			System.out.println("文件"+dateFile+"不是文件");
		}
		//实例化一个读取文件的对象
		DataInputStream dis=new DataInputStream(new FileInputStream(dateFile));
		//实例化一个写文件的对象
		DataOutputStream dos=new DataOutputStream(new FileOutputStream("Demo\\datafile1.pdf"));
		int length=0;
		byte[] buf=new byte[20*1024];
		while((length=dis.read(buf, 0, buf.length))!=-1){
			dos.write(buf);
		//	dos.flush();
		}
		//关闭文件
		dis.close();
		dos.close();
	}
	
	
	
	public static void bufferedFileToCopy(File bufferedFile)throws IOException{
		if(!bufferedFile.exists()){
			System.out.println("文件"+bufferedFile+"不存在");
		}
		if(!bufferedFile.isFile()){
			System.out.println("文件"+bufferedFile+"不是文件");
		}
		BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("Demo\\bufferedfile1.pdf"));
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(bufferedFile));
		int length=0;
		byte[] buf=new byte[20*1024];
		while((length=bis.read(buf, 0, buf.length))!=-1){
			bos.write(buf);
			bos.flush();
		}
		bis.close();
		bos.close();
	}
}

8.5 字符流

1.编码问题(看前面所描述的)。

2.认识文本与文本文件

Java的文本(char型)是16为无符号编码,是字符的Unicode编码(双字节编码)

文本是byte byte byte的数据序列。

文本文件是文本(char)序列按照某种编码方案(utf-8,utf-16be,gbk)序列化为byte的存储。

3.字符流分为输入流(writer)和输出流(reader)。操作的是文本、文本文件字符的处理,一次处理一个字符。

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

字符流的基本实现:

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

InputStreamWriter:完成char流到byte流的解析,按照编码处理

 

4、FileReader&FileWriter:

可以直接写文件名的路径。与InputStreamReader相比坏处:无法指定读取和写出的编码,容易出现乱码。

FileReader fr=new FileReader(“Demo\\im.txt”);//输出流

FileWriter fw=new FileWriter(“Demo\\im2.txt”);输入流

8.6字节流的过滤器

BufferedReader--àreadLine();一次读取一行,但不能识别换行。。

BufferedWriter/PrintWriter--à一次写一行

 

如:一次写入一行

BufferedWriter               PrintWriter

bw.wrire(line)               pw.println(line);//自动换行,不加ln不换行

bw.newLine();//单独换行       pw.flush();//刷新数据

bw.flush();//刷新数据

 

 

代码如下:

package com.ll.iofile;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

/**
 * 这个例子是用来测试字节流的过滤器
 * BufferedReader和BufferedWriter/PrintWriter类的使用
 * @author LULEI
 *
 */
public class testBufferedReaderAndBufferedWriter {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		//实例化一个BufferedReader的对象
		BufferedReader br=new BufferedReader(new InputStreamReader(
				new FileInputStream("C:\\Users\\Administrator\\Desktop\\搜狗.txt")));
		//实例化一个BufferedWriter的对象
		BufferedWriter wr=new BufferedWriter(
				new OutputStreamWriter(
						new FileOutputStream("Demo\\immoc1.txt")));
		//实例化一个PrintWriter的对象
		PrintWriter pw=new PrintWriter(
				new OutputStreamWriter(
						new FileOutputStream("Demo\\imooc2.txt")));
		
		String line=new String();
		while((line=br.readLine())!=null){
			/*测试BufferedWriter的write方法
			wr.write(line);//这样直接输入的只会在一行显示
			wr.newLine();//这句话起到读取一行就换行的作用
			wr.flush();
			*/
		//System.out.println(line);//每读取一行字节,直接输出
			//测试PrintWriter的方法
			pw.println(line);//输出一行字节的内容,且加ln自动换行
			pw.flush();
		}
		wr.close();
		br.close();
		pw.close();
	}

}

8.7对象的序列化与反序列化

1、对象的序列化是指将object对象转换成byte序列,反之将byte序列转换为object对象称之为反序列化。

2、序列化流(objetcOutputStream),是过滤流---writeObject

反序列化流(objectInputStream),readObject的使用需要进行强制类型的转换。

3、序列化接口(serializable)

对象必须实现序列化接口才能进行序列化,否则将会出现异常。这个接口没有任何的方法,只是一个标准。

 

代码如下:

package com.ll.iofile;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 这个类是用于测试对象的序列化和反序列化
 * 调用ObjectOutputSrteam 和ObjectInputStream类的使用
 * @author LULEI
 *
 */
public class testObjectSerializableDemo {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		//1、实现对象的序列化流的对象
		String file="Demo/object.txt";
		ObjectOutputStream oos=new ObjectOutputStream(
				new FileOutputStream(file));
		//实例化一个MobilePhone对象
		MobilePhone mp=new MobilePhone(4, 5.5f, "红米Note");
		//开始写对象
		oos.writeObject(mp);
		//刷新缓冲区数据
		oos.flush();
		oos.close();
		
		//2实现对象的反序列化流对象
		ObjectInputStream ois=new ObjectInputStream(
				new FileInputStream(file));
		//必须进行强制类型转换
		MobilePhone mps=(MobilePhone)ois.readObject();
		System.out.println(mps);
		ois.close();
	}

}


package com.ll.iofile;

import java.io.Serializable;

/**
 * 这个类是用于参与测试对象的序列化和反序列化
 * ObjectOutputSrteam 和ObjectInputStream类的使用
 * @author LULEI
 *
 */
//这里必须要继承serializable接口
public class MobilePhone implements Serializable {
	private int cpu;
	
	private float screen;
	
	private String name;
	public MobilePhone(){
		
	}
	
	public MobilePhone(int cpu, float screen, String name) {
		super();
		this.cpu = cpu;
		this.screen = screen;
		this.name = name;
	}

	public int getCpu() {
		return cpu;
	}
	public void setCpu(int cpu) {
		this.cpu = cpu;
	}
	public float getScreen() {
		return screen;
	}
	public void setScreen(float screen) {
		this.screen = screen;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "MobilePhone [cpu=" + cpu + ", screen=" + screen + ", name="
				+ name + "]";
	}
	
}

8.8 transient关键字

transient关键字修饰的属性默认是不能序列化的,但是可以使用writeObject自己完成这个元素的序列化。ArrayList就是用了此方法进行了优化的操作。ArrayList最核心的容器Object[] elementData使用了transient修饰,但是在writeObject自己实现对elementData数组的序列化。只能序列化数组中真实存在的元素,对于数组中的空的元素时不能进行序列化的。

如:

private void writeObject(java.io.ObjectOutputStream s) throws

java.io.IOException{

 

}

 

 

private void readObject(java.io.ObjectOutputStream s) throws

java.io.IOException,classNotFoundException{

 

代码如下:

package com.ll.iofile;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 这个类是用于测试对象的序列化和反序列化
 * 调用ObjectOutputSrteam 和ObjectInputStream类的使用
 * 1、首先实例化ObjectOutputSrteam 和ObjectInputStream类的对象oos和ois
 * 2、实例化将要序列化的对象qq
 * 3、对象oos调用writeObject()方法来对对象qq进行序列化流的输出操作。
 * 4、对象ois调用readObject()方法来进行反序列化的输入操作。同时要使用强制类型转换来转化
 * 赋值给相应的实例化对象x。
 * 4、最后直接输出x的内容
 * @author LULEI
 *
 */
public class testTransient {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		//1、实例化首先实例化ObjectOutputSrteam 和ObjectInputStream类的对象
		String file=new String("Demo\\testTransient");
		ObjectOutputStream oos=new ObjectOutputStream(
				new FileOutputStream(file));
		ObjectInputStream ois=new ObjectInputStream(
				new FileInputStream(file));
		//2、实例化将要被序列化的对象MobilePhone
		MobilePhone2 mp=new MobilePhone2(4, 4.0f, "华为");
		//3、oos对象调用writeObject()方法来进行序列化
		oos.writeObject(mp);
		oos.flush();//刷新缓冲区
		oos.close();//关闭文件流
		//4、ois对象调用readObject方法来进行反序列化的操作,同时赋值给相应类型的对象
		try {
			MobilePhone2 mps=(MobilePhone2)ois.readObject();
			System.out.println(mps);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ois.close();
	}

}




package com.ll.iofile;

import java.io.Serializable;

/**
 * 这个类是用于参与测试对象的序列化和反序列化
 * ObjectOutputSrteam 和ObjectInputStream类的使用
 * 同时检测了transient关键字的使用
 * @author LULEI
 *
 */
//这里必须要继承serializable接口
public class MobilePhone2 implements Serializable {
	private int cpu;
	//使用transient关键字修饰,这时screen的值不会被序列化。这时
	//如果想进行序列化,只能够自己人为的进行序列化
	private transient float screen;
	
	private String name;
	public MobilePhone2(){
		 
	}
	
	public MobilePhone2(int cpu, float screen, String name) {
		super();
		this.cpu = cpu;
		this.screen = screen;
		this.name = name;
	}
	/*这里是自己认为的完成序列化的操作
	//人工的进行序列化
	private void writeObject(java.io.ObjectOutputStream s)
	        throws java.io.IOException{
			s.defaultWriteObject();//则是执行默认的序列化操作
			s.writeFloat(screen);//自己人工的进行screen序列化操作
	}
	//人工的进行反序列化的操作
	 private void readObject(java.io.ObjectInputStream s)
		        throws java.io.IOException, ClassNotFoundException {
		 s.defaultReadObject();//执行默认的反序列化的操作
		 this.screen=s.readFloat();//自己完成screen的反序列化的操作
	 }
	 */
	public int getCpu() {
		return cpu;
	}
	public void setCpu(int cpu) {
		this.cpu = cpu;
	}
	public float getScreen() {
		return screen;
	}
	public void setScreen(float screen) {
		this.screen = screen;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "MobilePhone [cpu=" + cpu + ", screen=" + screen + ", name="
				+ name + "]";
	}
	
}

8.9序列化过程中子父类构造函数的问题

1>父类实现了serializable接口,子类继承父类就可以序列化了。

2>但子类在进行反序列化的时候,父类 实现了序列化接口,则不会递归调用其构造函数。

 

3>父类未实现了serializable接口,子类自己实现了接口,子类可以自行实现可序列化。

4>子类在反序列化时,父类没有实现序列化的接口,则会递归调用其构造函数。

  

2015年3月29日   XXiaoLEI整理 


你可能感兴趣的:(java,字节流,字符流,io操作,序列化与反序列)