(黑马程序员)学习笔记,其他IO流对象

1. ObjectInputStream和ObjectOutputStream

package io;

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

/**
 * 1、序列化是干什么的?

  简单说就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存Object States,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

2、什么情况下需要序列化 

a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;

3、当对一个对象实现序列化时,究竟发生了什么?

在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如:

Foo myFoo = new Foo(); 
myFoo .setWidth(37); 
myFoo.setHeight(70); 

  当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它 从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对 象。

FileOutputStream fs = new FileOutputStream("foo.ser"); 
ObjectOutputStream os = new ObjectOutputStream(fs); 
os.writeObject(myFoo); 

4、实现序列化(保存到一个文件)的步骤

a)Make a FileOutputStream 
java 代码
FileOutputStream fs = new FileOutputStream("foo.ser"); 
b)Make a ObjectOutputStream 

java 代码
ObjectOutputStream os = new ObjectOutputStream(fs); 
c)write the object

java 代码
os.writeObject(myObject1); 
os.writeObject(myObject2); 
os.writeObject(myObject3); 
d) close the ObjectOutputStream

java 代码
os.close(); 

5、举例说明

java 代码
import java.io.*; 

public class Box implements Serializable 
{ 
private int width; 
private int height; 

public void setWidth(int width){ 
this.width = width; 
} 
public void setHeight(int height){ 
this.height = height; 
} 

public static void main(String[] args){ 
Box myBox = new Box(); 
myBox.setWidth(50); 
myBox.setHeight(30); 

try{ 
FileOutputStream fs = new FileOutputStream("foo.ser"); 
ObjectOutputStream os = new ObjectOutputStream(fs); 
os.writeObject(myBox); 
os.close(); 
}catch(Exception ex){ 
ex.printStackTrace(); 
} 
} 

} 

6、相关注意事项

a)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
b)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
c)并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了,比如:

  1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
  2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分 配,而且,也是没有必要这样实现。
 * @author asus
 *
 */
public class ObjectStreamDemo {
	
	public static void main(String[] args) {
		try {
			writeObj();
			readObj();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private static void writeObj() throws IOException{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\BaiduYunDownload\\FILE\\obj")));
		oos.writeObject(new Person("test",99));
		oos.close();
	}
	private static void readObj() throws IOException, ClassNotFoundException{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:\\BaiduYunDownload\\FILE\\obj")));
		Person p = (Person)ois.readObject();
		System.out.println(p.toString());
		ois.close();
	}
}

//序列化
class Person implements Serializable{
	//手动匹配序列号
	private static final long serialVersionUID = 42L;
	private String name;
	private int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String toString(){
		return name+".."+age;
	}
}

2. PipedInputStream 和PipedOutputStream

package io;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/*
 * 管道流对象 PipedInputStream PipedOutputStream,输入输出可以直接连接的特殊流对象,应该通过多线程使用以免死锁。
 */
public class PipedStreamDemo {

	public static void main(String[] args) {
		//创建管道流对象
		PipedInputStream in = new PipedInputStream();
		PipedOutputStream out = new PipedOutputStream();
		try {
			//将输入输出管道流连接
			in.connect(out);
			//将管道流添加到多线程中
			Read r = new Read(in);
			Writer w = new Writer(out);
			//创建线程
			Thread tr = new Thread(r);
			Thread tw = new Thread(w);
			//开启线程
			tr.start();
			tw.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

class Read implements Runnable{

	private PipedInputStream pipIn;
	//通过构造函数传入PipedInputStream对象
	public Read(PipedInputStream pipIn){
		this.pipIn = pipIn;
	}
	public void run() {
		try {
			//读取数据
			byte[] buf = new byte[1024];
			int len = pipIn.read(buf);
			String s = "没有数据";
			if(len!=-1){
				s = new String(buf,0,len);
			}
			
			System.out.println(s);
			
		} catch (IOException e) {
			throw new RuntimeException("管道流读取失败");
		}finally{
			if(pipIn!=null){
				try {
					pipIn.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}

class Writer implements Runnable{

	private PipedOutputStream pipOut;
	public Writer(PipedOutputStream pipOut){
		this.pipOut = pipOut;
	}
	public void run() {
		try {
			//写入数据
			pipOut.write("管道TEST".getBytes());
		} catch (IOException e) {
			throw new RuntimeException("管道流输出失败");
		}finally{
			if(pipOut!=null){
				try {
					pipOut.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}

3. RandomAccessFile

package io;

import java.io.IOException;
import java.io.RandomAccessFile;

/*
 * RandomAccessFile
 * 
 * 该类不是IO体系中的子类,而是直接继承自Object
 * 既能读又能写,封装了数组和指针
 * 
 * 但是他是IO包中的成员,因为它具备读和写功能,内部封装了一个数组,而且通过指针对数组中的元素进行操作
 * 可以通过getFilePointer获取指针位置,同时通过seek改变指针的位置
 * 
 * 内部封装了字节输入输出流,该类只能操作文件,并且还有操作模式:只读"r" 读写"rw"
 * 如果模式为"r",不会创建文件,只读取已存在的文件,如果文件不存在,则出现异常。
 * 如果模式为"rw",操作文件不存在,会自动创建文件。
 */
public class RandomAccessFileDemo {

	public static void main(String[] args) {
		String dir = "E:\\BaiduYunDownload\\FILE";
		try {
			writeFile(dir);
			System.out.println("数据已输出");
			readFile(dir);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void writeFile(String dir) throws IOException{
		//创建RandomAccessFile对象,设置读写模式
		RandomAccessFile raf = new RandomAccessFile(dir+"\\raf.txt", "rw");
		//写入
		raf.write("张三".getBytes());
		raf.writeInt(65);
		raf.write("李四".getBytes());
		raf.writeInt(97);
		raf.close();
	}
	
	private static void readFile(String dir) throws IOException{
		RandomAccessFile raf = new RandomAccessFile(dir+"\\raf.txt", "r");
		//调整指针
		raf.seek(4*2);
		//读取四个字节
		byte[] buf = new byte[4];
		int len = raf.read(buf);
		String s = "";
		if(len!=-1){
			s = new String(buf,0,len);
		}
		System.out.println(s);
		raf.close();
	}
}

4. DataInputStream 和 DataOutputStream

package io;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/*
 * 用于操作基本类型的数据流对象
 */
public class DataStreamDemo {

	public static void main(String[] args) {
		String dir = "E:\\BaiduYunDownload\\FILE";
		try {
			writeDataUTF(dir);
//			readData(dir);
			
			//用转换流的方法,输出utf-8编码的字符流
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File(dir+"\\osw.txt")),"utf-8");
			osw.write("测试");
			osw.close();
			
			readDataUTF(dir);
			System.out.println("完成");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	//使用utf-8改版字符码表来输出数据,输出后只能使用readUTF()来读取
	private static void writeDataUTF(String dir) throws IOException{
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(dir+"\\dosUTF.txt")); 
		dos.writeUTF("测试");
		dos.close();
	}
	//使用utf-8改版字符码表来读取数据
	private static void readDataUTF(String dir) throws IOException{
		DataInputStream dis = new DataInputStream(new FileInputStream(dir+"\\dosUTF.txt"));
		String s = dis.readUTF();
		System.out.println("字符串:"+s);
		dis.close();
	}
	//输出基本类型数据
	private static void writeData(String dir) throws IOException{
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(dir+"\\dos.txt")); 
		dos.writeInt(423);
		dos.writeBoolean(true);
		dos.writeDouble(11.22);
		
		dos.close();
	}
	//按着顺序读取基本数据类型数据
	private static void readData(String dir) throws IOException{
		DataInputStream dis = new DataInputStream(new FileInputStream(dir+"\\dos.txt")); 
		int num = dis.readInt();
		boolean b = dis.readBoolean();
		double d = dis.readDouble();
		System.out.println("数字:"+num+"\n"+"布尔:"+b+"\n"+"小数:"+d+"\n");
		dis.close();
	}
	
}

5. ByteArrayInputStream 和 ByteArrayOutputStream

package io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/*
 * 用于操作字节数组的流对象
 * 
 * ByteArrayInputStream:构造时需要接收数据源,而且数据源是一个字节数组。
 * ByteArrayInputStream:构造时不需要定义数据源,而是在内部封装了一个可变长度的字节数组。
 * 
 * 因为两个流对象都操作数组,并没有使用系统资源,所以不用关闭。
 * 
 * 跟它类似的还有:	字符数组流CharArrayReader、ChararrayWriter 
 * 				字符串流 StringReader、StringWriter
 */
public class ByteArrayStreamDome {

	public static void main(String[] args) {
		//数据源
		byte[] buf = "ABCDEFG".getBytes();
		ByteArrayInputStream in = new ByteArrayInputStream(buf);
		//数据目的
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int len = 0;
		while((len=in.read())!=-1){
			out.write(len);
		}
		
		System.out.println(out.toString());
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值