您的位置:首页 > 编程语言 > Java开发

Java学习总结(8)—内存流,打印流,对象流,RandomAccessFile,装饰者设计模式

2018-02-12 21:20 507 查看
一.内存流内存流主要用来操作内存
BytearrayInputStream和ByteArrayOutputStream输入和输出可以把文件作为数据源,也可以把内存作为数据源(1)ByteArrayInputStream主要完成将内容从内存读入到程序中,而ByteArrayOutputStream的主要功能是是将数据写入到内存中(2)注意:因为这两个流没有使用系统资源,所以不用关闭,也不需要抛出异常
内存操作示意图(1)从程序中读:程序<—ByteArrayInputStream<—内存数据(2)向内存中写:程序—>ByteArrayOutputStream<—内存数据
ByteArrayOutputStream获取数据的方式(1)public byte[] toByteAarray():创建一个新分配的字节数组,它的大小 是这个输出流的当前大小和缓冲区的有效内容的副本(2)public Stirng toString():使用该平台默认的字符集将缓冲区的内容的转换为字符串
例1(利用内存流复制图片):package bytestream; import java.io.*; public class ByteOutputStreamDemo { public static void main(String[] args) { File srcFile = new File("d:" + File.separator + "1TX761XVUM10.jpg");// 源文件地址 File destFile = new File("e:" + File.separator + srcFile.getName());// 目标文件地址 InputStream input = null;// 输入流 OutputStream out = null;// 输出流 ByteArrayOutputStream bos = new ByteArrayOutputStream();// 内存流 try { input = new FileInputStream(srcFile);// 对象用于读取源文件 out = new FileOutputStream(destFile);// 对象用于写入目标文件 byte[] b = new byte[1024]; int len = 0; // 边读编写 System.out.println("开始复制文件!"); while ((len = input.read(b)) != -1) { bos.write(b, 0, len); } byte[] date = bos.toByteArray();// 创建一个新的字节数组,他的大小是这个输出流的当前大小,和缓冲区的有效 内容的副本 out.write(date);// 讲缓冲区中的内容一次性写入到目标文件中 System.out.println("文件复制完毕......"); } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭资源 out.close(); input.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } } }运行结果:开始复制文件!文件复制完毕.....例2(以byteArrayInputStream为例):package bytestream; import java.io.*; public class ByteArrayInputStreamDemo { public static void main(String[] args) {String date="世界,你好!!!!";/** * 内存输入流中传入的参数为要读取的字节数组,故将date * 转化为字节数组date.getBytes(),再传入内存流中 */ByteArrayInputStream bis = new ByteArrayInputStream(date.getBytes());byte[] b=new byte[1024];//自定义缓存区int len=0;try {len=bis.read(b);System.out.println("读取到的内容是:"+new String(b,0,len));} catch (IOException e) {e.printStackTrace();}//数据存于缓存区中,缓存流不用关闭} }运行结果:读取到的内容是:世界,你好!!!! 二.打印流打印流提供了打印方法,可以将各种数据类型原样打印,可以操作输出流和文件
PrintStream:(1)提供操作字节功能(2)如果包装的是缓冲流可自动设置flush(3)可设置字符集
PrintWriter:(1)没有操作字节功能(2)内部有缓冲区,即使自动刷新设置为true(3)可设置字符集
打印流的构造方法<1>PrintStream的构造方法(1)public PrintStream(File file)(2)public PrintStream(OutputStream out)<2>PrintWriter的构造方法(1)public PrintWriter(File file)(2)Public PrintWriter(Writer out)(3)Public PrintWriter(OutputStream out)
例1(写入一首诗到C盘文件下):package print; import java.io.*; public class PrintStreamDemo { public static void main(String[] args) {File f=new File("C:"+File.separator+"静夜诗.txt");PrintStream ps=null;try {ps=new PrintStream(f);ps.println("\t床前明月光");ps.println("\t疑是地上霜");ps.println("\t举头望明月");ps.println("\t低头思故乡");ps.println("\t\t\t作者:李白");System.out.println("打印成功...");} catch (FileNotFoundException e) {e.printStackTrace();}finally{ps.close();}} }运行结果:打印成功...例2(PrintStream若包装缓冲流可设置flush):package print; import java.io.*; public class PrintStreamDemo2 { public static void main(String[] args) {File f=new File("c:"+File.separator+"兵法.txt");PrintStream ps=null;OutputStream out=null;try {out=new FileOutputStream(f);BufferedOutputStream bos= new BufferedOutputStream(out);ps=new PrintStream(bos);ps.println("战武七经:");ps.println("1.孙子兵法");ps.println("2.六韬.三略");ps.println("3.吴子");ps.println("4.司马法");ps.println("5.孙膑兵法");ps.flush();//将缓冲流中的数据刷入文件中System.out.println("打印成功....");} catch (FileNotFoundException e) {e.printStackTrace();}} }运行结果:打印成功....三.对象流,序列化与反序列化相关类(1)ObjectOutputStream(用于序列化)(2)ObjectInputStream(用户反序列化)2.适用对象流可以实现对象不得序列化与反序列化操作3.为什么要序列化(1)易于保存(2)易于保存4.序列化与反序列化的过程(1)序列化:Java对象——>对象的二进制形式(2)反序列化:Java对象<——对象的二进制形式*这种方式被称为序列化与反序列化<1>序列化是将对象的状态存储到特定的存储介质中的过程(将对象转化成特定的字节序列(二进制)的过程)<2>反序列化则是从特定的存储介质中的数据重新构建对象的过程(将对象的二进制形式转化成对象)5.序列化的步骤 (1)实现Serializble接口(2)创建对象输出流(3)调用writeObject(Object obj)方法将对象写入输出流中(4)关闭对象输出流6.反序列化步骤(1)实现Serializble接口(2)创建对象输入流(3)调用readObject()方法读取对象(4)关闭对象输入流@@创建Person用于举例:package serializable; import java.io.Serializable; public class Person implements Serializable { /** * 对象类,用于序列化 */private static final long serialVersionUID = 1L;private String name;private int age;private double score; public Person() {super();} public Person(String name, int age, double score) {super();this.name = name;this.age = age;this.score = score;} public String getName() {return name;} public void setName(String name) {this.name = name;} public int getAge() {return age;} public void setAge(int age) {this.age = age;} public double getScore() {return score;} public void setScore(double score) {this.score = score;} public static long getSerialversionuid() {return serialVersionUID;} @Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", score=" + score+ "]";} } 例1(序列化普及对象)package serializable; import java.io.*; public class SerialPerson { public static void main(String[] args) {File f=new File("d:"+File.separator+"Serbial.txt");ObjectOutputStream oos=null;OutputStream out=null;Person per=new Person("Jack",21,98.7);try {System.out.println("开始序列化");out=new FileOutputStream(f);oos=new ObjectOutputStream(out);oos.writeObject(per);System.out.println("系列化 成功......");} catch (Exception e) {e.printStackTrace();}finally{try {out.close();oos.close();} catch (IOException e) {e.printStackTrace();}} } }运行结果:开始序列化系列化 成功...... 例2(普通反序列化)package serializable; import java.io.*; public class DeSerialPerson { public static void main(String[] args) {File f = new File("d:" + File.separator + "Serbial.txt");InputStream input = null;ObjectInputStream ois = null;try {System.out.println("开始反序列化!!!");input = new FileInputStream(f);ois = new ObjectInputStream(input);Person per=(Person)ois.readObject();System.out.println("反序列化成功。。。。。");} catch (Exception e) {e.printStackTrace();}finally{try {ois.close();input.close();} catch (IOException e) {e.printStackTrace();}}} }运行结果:开始反序列化!!!Person [name=Jack, age=21, score=98.7]例3(序列化集合)package serializable; import java.io.*;import java.util.*; public class SerialListDemo { public static void main(String[] args) {File f=new File("d:"+File.separator+"listSer.txt");List<Person> list=new ArrayList<Person>();Collections.addAll(list, new Person("郭靖",21,96.2),new Person("黄蓉",22,93.2),new Person("小龙女",19,94.6),new Person("杨过",15,95.3));OutputStream out=null;ObjectOutputStream oos=null;try {System.out.println("开始序列化");out=new FileOutputStream(f);oos=new ObjectOutputStream(out);oos.writeObject(list);System.out.println("系列化成功.......");} catch (Exception e) {e.printStackTrace();}finally{try {out.close();oos.close();} catch (IOException e) {e.printStackTrace();}}}}运行结果为:开始序列化系列化成功....... 例4(反序列化集合)package serializable; import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.util.List; public class DeSerialList { public static void main(String[] args){File f=new File("d:"+File.separator+"listSer.txt");InputStream input=null;ObjectInputStream ois=null;try {System.out.println("开始反序列化");input=new FileInputStream(f);//输入流ois=new ObjectInputStream(input);//封装输入流到对象流中List<Person> list=(List<Person>)ois.readObject();//向上 转型for(Person per:list){System.out.println( per);}} catch (Exception e) {e.printStackTrace();}finally{try {input.close();ois.close();} catch (IOException e) {e.printStackTrace();}} } }运行结果:开始反序列化Person [name=郭靖, age=21, score=96.2]Person [name=黄蓉, age=22, score=93.2]Person [name=小龙女, age=19, score=94.6]Person [name=杨过, age=15, score=95.3]四.RandomAccessFile1.直接继承Object2.主要功能是完成随机读写功能,可以读取指定位置的内容3.构造方法:
(1)public RandomAccessFile(File file,String mode)(2)public RanaccessFile(String name,String mode)(3)只能操作文件4.文件的打开模式(mode)(1)”r”以只读方式打开,调用结果对象的任何write方法都将抛出异常IOException(2)“rw”打开以便于读取和写入,如果该文件上不存在,则尝试创建该文件5.RandomAccessFile的常用方法(1)void seek(long pos)设置文件指定偏移量, 在该位置准备开始读写(2)Int sikpByte(int n)尝试跳过输入的n个字节,返回实际跳过的字节数(3)Long getFilePointer()获取此文件中的 当前偏移量(4)Long length()返回此文件的长度(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 witreBoolean(boolean v)(15)Void writeByte(int v)(16)Void writeChar(int v)(17)Void writeInt(int v)例1.(以RandomAccessFile基本方法为例)package raf; import java.io.File;import java.io.IOException;import java.io.RandomAccessFile; public class RandomAccessFileDemo { public static void main(String[] args) {File f=new File("d:"+File.separator+"Ran.txt");RandomAccessFile raf=null;try {raf=new RandomAccessFile(f,"rw");raf.writeBoolean( true);raf.writeChar('A');raf.writeChars("hello");raf.writeChars("中华人名共和国");System.out.println("写入成功....."); raf.seek(9);System.out.println("文件当前位置指针:"+raf.getFilePointer());System.out.println("当前位置字符:"+raf.readChar());raf.seek(3);System.out.println("文件当前位置指针:"+raf.getFilePointer());System.out.println("当前位置字符:"+raf.readChar());raf.seek(10);System.out.println("文件当前位置 指针"+raf.getFilePointer());System.out.println("文件当前位置在字符:"+raf.readChar());} catch (Exception e) {e.printStackTrace();}finally{try {raf.close();} catch (IOException e) {e.printStackTrace();}}} }运行结果:写入成功.....文件当前位置指针:9当前位置字符:l文件当前位置指针:3当前位置字符:h文件当前位置 指针10文件当前位置在字符:氀 例2(RandomAccessaFile注意点)package raf; import java.io.File;import java.io.IOException;import java.io.RandomAccessFile; public class RafString { public static void main(String[] args) {File f=new File("d:"+File.separator+"raf.txt");RandomAccessFile raf=null;try {raf=new RandomAccessFile(f,"rw");raf.writeBytes("中华人民共和国");//会丢弃高八位的方式写入字符串中的每个字符raf. writeChars("中央 人民政府");//会将字符串中的每个字符写入raf.seek(3);//设置文件指针System.out.println("当前 指针位置的字符为:"+raf.readChar());} catch (Exception e) {e.printStackTrace();}finally{try {raf.close();} catch (IOException e) {e.printStackTrace();}}} }运行结果为:当前 指针位置的字符为:?
五.装饰者模式当需要对已有的对象进行功能增强时,可以定义类(装饰类),将已有的对象的话传入,基于已有的功能,并提供增强功能,那么自定义的类称为装饰 类
相同点:装饰者模式与继承关系的目的都是要扩展对象的功能
不同点:(1)代码的结构比继承更加简洁(2)装饰者模式可以提供比继承更多的灵活性(意味着可以向装饰器的构造方法传入被装饰类的子类对象)
装饰者设计模式的特点(1)装饰对象和真实对象有相同的接口或抽象类(2)装饰对象包含一个真实对象的引用(3)装饰对象接收所有来自客户端的请求,他把这些请求转发给真实对象(4)装饰对像可以在转发这些请求之前或之后增加一些附加的功能
装饰者设计模式的结构(1)抽象构建角色:给出一个抽象接口,以规范准备接受附加责任的对象,相当于IO流中的InputStream/OutputStream(2)具体构建角色:定义一个将要接受附加责任的类,相当于IO流中的FileInputStream/FileOutputStream(3)抽象装饰角色:持有一个抽象构建角色(也就是Component)的引用,并实现这个与抽象构建接口,相当于FileterInputStream/FileterOutputStream(4)具体的装饰角色:负责给构建对象“贴上”附加的责任。相当于BufferedInputStream/BufferedOutputStream例.(装饰一个学生的学习方法)*抽象构建接口package decorator;/** * 抽象构建接口 * @author Qitao */public interface Study {public void study();}*具体构建角色package decorator;/** * 具体构建角色 * @author Administrator */public class Student implements Study{ @Overridepublic void study() {System.out.println("学生正在学习...");} }*抽象装饰角色package decorator;/** * 抽象装饰角色 * @author Administrator */ public abstract class Decorator implements Study{private Study study; public Decorator(Study study) {super();this.study = study;} @Overridepublic void study() {this.study.study();}}*具体装饰角色package decorator;/** * 具体装饰角色 * @author Administrator */public class ConcreteDecorator extends Decorator{ public ConcreteDecorator(Study study) {super(study);} public void goodStudy(){System.out.println("课前预习...");super.study();System.out.println("课后复习...");}}*测试装饰者设计模式类:package decorator;/** * 测试装饰者设计模式 * @author Administrator */public class Test {public static void main(String[] args){Study study=new Student();ConcreteDecorator con=new ConcreteDecorator(study);con.goodStudy();} } 运行结果:课前预习...学生正在学习...课后复习...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐