内存流,打印流,对象流,序列化与反序列化

声明:由于学习所用环境为JDK1.8,所有java代码均在JDK1.8环境中测试通过,如果环境发生变化,可能会有错误发生!

一.内存流

1、内存流主要用来操作内存

输入输出可以把文件当做输入源,也可以把内存当做输入源。

ByteArrayInputStream:负责把内存中的数据读入程序中;

ByteArrayOutputStream:负责把程序中的数据写入内存中。

注意:由于内存流操作的是内存,没有占用系统内存和使用系统资源,所以不需要,也不需要抛出异常

2、内存流操作示意图


3、ByteArrayOutputStream获取数据的方式

(1) public byte[] toByteArray()

创建一个新分配的字节数组。它的大小是这个输出流的当前大小和缓冲区的有效内容的副本

(2)public String toString()

使用该平台的默认字符集将缓冲区的内容转换为字符串

package memory;

import java.io.*;

public class BostoByteArray {

	public static void main(String[] args) {
		File srcFile=new File("e:"+File.separator+"picture"+File.separator+"6.jpg");
		File destFile=new File("c:"+File.separator+srcFile.getName());
		InputStream input=null;
		OutputStream out=null;
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
		try {
			input=new FileInputStream(srcFile);
			out=new FileOutputStream(destFile);
			int len=0;
			byte[] b=new byte[1024];     //定义缓冲区
			while((len=input.read(b))!=-1){
				bos.write(b,0,len);     //不断写入内存中
			}
			byte[] array=bos.toByteArray();   //传建一个新分配的字节数组,它的大小是输出流的当前大小和缓冲区大小的副本
			out.write(array);        //一次性写到磁盘
			System.out.println("复制成功!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
package memory;

import java.io.*;

public class BostoString {

	public static void main(String[] args) {
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		try {
			bos.write("hello world西安理工大学".getBytes("utf-8"));
			System.out.println(bos.toString("utf-8"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
二.打印流

1、打印流提供了打印方法,可以将各种数据类型原样打印,可以操作输出流和文件
(1)PrintStream
提供操作字节功能
如果包装的是缓冲流可设置自动flush
可设置字符集
(2)PrintWriter
没有操作字节功能
内部有缓冲区,即使自动刷新设置为true
可设置字符集

2、打印流的构建方法

(1)PrintStream的构造方法:
public PrintStream(File  file)
public PrintStream(OutputStream out)

(2)PrintWriter的构造方法
public PrintWriter(File  file)
public PrintWriter(Writer out)
public PrintWriter(OutputStream out)

package print;

import java.io.*;

public class PrintStreamDemo {

	public static void main(String[] args) {
		File f=new File("d:"+File.separator+"test.txt");
		PrintStream ps=null;
		OutputStream out=null;
		BufferedOutputStream bos=null;
		try {
			out=new FileOutputStream(f);
		        bos=new BufferedOutputStream(out);
		        ps=new PrintStream(bos);
			ps.println('M');
			ps.println(true);
			ps.println(9);
			ps.flush();
			System.out.println("写入成功!");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

}
package print;

import java.io.*;

public class PrintWriterDemo {

	public static void main(String[] args) {
		File f=new File("d:"+File.separator+"test.txt");
		PrintWriter pw=null;
		try {
			pw=new PrintWriter(f);
			pw.println('M');
			pw.println(false);
			pw.println("中国");
			
			pw=new PrintWriter(new FileWriter(f));
			pw.println(true);
			
			pw=new PrintWriter(new FileOutputStream(f));
			pw.println("hello java");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

三.对象流、序列化与反序列化

1、相关类:

ObjectOutputStream(用于序列化)

ObjectInputStream(用于反序列化)

使用对象流可以实现对象的序列化与反序列化操作

序列化的目的:易于保存,易于传输。

2、序列化与反序列化的过程


3、序列化的步骤


4、反序列化的步骤


package serial;

import java.io.*;

public class SerialDemo {

	public static void main(String[] args) {
		Student student=new Student("李丽",18,"女",89.0);
		File file=new File("d:"+File.separator+"student.txt");
		OutputStream out=null;
		ObjectOutputStream oos=null;
		try {
			out=new FileOutputStream(file);
			oos=new ObjectOutputStream(out);
			oos.writeObject(student);
			System.out.println("序列化成功!");
		} catch (Exception e){
			e.printStackTrace();
		}
	}
}
package serial;

import java.io.*;

public class SerialDe {

	public static void main(String[] args) {
		File file=new File("d:"+File.separator+"student.txt");
		InputStream input=null;
		ObjectInputStream ois=null;
		OutputStream out=null;
		try {
			input=new  FileInputStream(file);
			ois=new ObjectInputStream(input);
			Student stu=(Student)ois.readObject();
			System.out.println(stu);
			System.out.println("反序列化完成");
			BufferedWriter bw=new BufferedWriter(new OutputStreamWriter
                        (new FileOutputStream("e:"+File.separator+"abc.txt")));
			String str=stu.toString();
			bw.write(str);
			bw.flush();
			System.out.println("保存成功!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

四、RandomAccessFile

1、(1)直接继承Object类

(2)主要功能是完成随机读写功能,可以读取指定位置的内容

(3)构造方法:

public RandomAccessFile(File file,String mode)

public RandomAccessFile(String name,String mode)

(4)只能操作文件

2、文件的打开模式(mode):
“r” 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。  
“rw” 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
 

3、RandomAccessFile常用方法

(1)void seek(long pos)设置文件指针偏移量,在该位置准备开始读写。
(2)int skipBytes(int n)尝试跳过输入的 n 个字节并丢弃跳过的字节.返回实际跳过的字节数
(3)long getFilePointer()获取此文件中的当前偏移量
(4)long length()返回此文件的长度。

package raf;

import java.io.File;
import java.io.RandomAccessFile;

public class RafDemo {

	public static void main(String[] args) {
		File f=new File("d:"+File.separator+"test.txt");
		RandomAccessFile raf=null;
		try {
			raf=new RandomAccessFile(f, "rw");
			raf.writeBoolean(true);   //一个字节
			raf.writeChars("西安理工大学");    //一个字符占两个字节
			raf.writeChar('M');    //一个字符占两个字节
			raf.seek(13);
			System.out.println("当前指针位置为"+raf.getFilePointer());
			System.out.println(raf.readChar());
			System.out.println("写入成功!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
(5)void write(int)向此文件写入指定的字节。
(6)void write(byte[])将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。
(7)void write(byte[] b, int off, int len)
(8)int read()从此文件中读取一个数据字节。
(9)int read(byte[] b)将最多 b.length 个数据字节从此文件读入 byte 数组。
(10)int read( byte[] b, int off, int len)
(11)void writeBytes(String s) 以字节为单位写出字符串,无法写出中文
(12)void writeChars(String s) ,每个字符占两个位置,可以写出中文,使用unicode编码。
(13)void writeUTF(String str)使用utf-8编码方式将一个字符串写出到该文件 ,可以写出中文
(14)void writeBoolean(boolean v)
(15)void writeByte(int v)
(16)void writeChar(int v)
(17)void writeInt(int v)
五、装饰者模式
当需要对已有的对象进行功能增强时,可以定义类(装饰类),将已有的对象传入,基于已有的功能,并提供加强功能,那么自定义的类成为装饰类
1、装饰者设计模式的特点:
装饰对象和真实对象有相同的接口或抽象类
装饰对象包含一个真实对象的引用
装饰对象接收所有的来自客户端的请求,它把这些请求转发给真实的对象
装饰对象可以在转发这些请求之前或之后增加一些附加的功能
2、装饰者设计模式的结构:
(1) 抽象构建角色(Component):
     给出一个抽象的接口,以规范准备接受附加责任的对象。相当于IO流里面的InputStream/OutputStream。
(2) 具体的构建角色(ConcreteComponent):
    定义一个将要接受附加责任的类。相当于IO里面的FileInputStream/FileOutputStream。
(3).抽象装饰角色(Decorator)
    持有一个抽象构建(也就是Component)的引用,并实现这个抽象构建接口。相当于FilterInputStream/FilterOutputStream
(4)具体的装饰角色(ConcreteDecorator)
    负责给构建对象“贴上”附加的责任。相当于BufferedInputStream/BufferedOutputStream。

package decorator;
/*
 * 抽象构建角色
 * */
public interface Love {
   public void love();
}
package decorator;
/*
 * 具体构建角色
 * */
public class Student implements Love{

	@Override
	public void love() {
       System.out.println("学生正在谈恋爱...");		
	}
}
package decorator;
/*
 * 抽象装饰角色
 * */
public abstract class Decorator implements Love{
   private Love love;   // 持有抽象构建角色的引用
   
   public Decorator(Love love){
	   this.love=love;
   }
   
   @Override
   public void love() {
	  this.love.love();		
   }
}
package decorator;
/*
 * 具体装饰角色
 * */
public class ConcreteDecorator extends Decorator{
	
   public ConcreteDecorator(Love love){
	   super(love);
   }
   
   public void beautifulLove(){
	   System.out.println("送花...");
	   super.love();
	   System.out.println("结婚...");
   }
}
package decorator;
public class Test {

	public static void main(String[] args) {
		Love love=new Student();
		ConcreteDecorator dec=new ConcreteDecorator(love);
		dec.beautifulLove();
		
	}
}

补充:

1、装饰者模式和继承的区别:

相同点
装饰模式与继承关系的目的都是要扩展对象的功能
不同点
代码结构比继承更加简洁
装饰模式可以提供比继承更多的灵活性(意味着可以向装饰器的构造方法传入被装饰类的子类对象)

2、组合与继承应用场景

继承是类与类或者接口与接口之间最常见的关系;继承是一种is-a关系
组合(Composition)体现的是整体与部分、拥有的关系,即has-a的关系
























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值