一.内存流

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

  2. BytearrayInputStreamByteArrayOutputStream输入和输出可以把文件作为数据源,也可以把内存作为数据源

    (1)ByteArrayInputStream主要完成将内容从内存读入到程序中,而ByteArrayOutputStream的主要功能是是将数据写入到内存中

    (2)注意:因为这两个流没有使用系统资源,所以不用关闭,也不需要抛出异常

  3. 内存操作示意图

    (1)从程序中读:程序<ByteArrayInputStream<—内存数据

    (2)向内存中写:程序>ByteArrayOutputStream<—内存数据

  4. 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();

}

//数据存于缓存区中,缓存流不用关闭

}

 

}

运行结果:读取到的内容是:世界,你好!!!!

 

二.打印流

  1. 打印流提供了打印方法,可以将各种数据类型原样打印,可以操作输出流和文件

  2. PrintStream:

    (1)提供操作字节功能

    (2)如果包装的是缓冲流可自动设置flush

    (3)可设置字符集

  3. PrintWriter

    (1)没有操作字节功能

    (2)内部有缓冲区,即使自动刷新设置为true

    (3)可设置字符集

  4. 打印流的构造方法

    <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();

}

}

 

}

运行结果:打印成功...

2PrintStream若包装缓冲流可设置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. 相关类

    1ObjectOutputStream(用于序列化)

    2ObjectInputStream(用户反序列化)

    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;

    }

     

    @Override

    public 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]

    四.RandomAccessFile

    1.直接继承Object

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

    3.构造方法:
    1public 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

    文件当前位置在字符:氀

     

    2RandomAccessaFile注意点)

    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. 相同点:装饰者模式与继承关系的目的都是要扩展对象的功能

  3. 不同点:

    (1)代码的结构比继承更加简洁

    (2)装饰者模式可以提供比继承更多的灵活性(意味着可以向装饰器的构造方法传入被装饰类的子类对象)

  4. 装饰者设计模式的特点

    (1)装饰对象和真实对象有相同的接口或抽象类

    (2)装饰对象包含一个真实对象的引用

    (3)装饰对象接收所有来自客户端的请求,他把这些请求转发给真实对象

    (4)装饰对像可以在转发这些请求之前或之后增加一些附加的功能

  5. 装饰者设计模式的结构

    (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{

     

    @Override

    public 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;

    }

     

    @Override

    public 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();

    }

     

    }

     运行结果:

    课前预习...

    学生正在学习...

    课后复习...