8.30 Bufferedxxx、对象流、标准输入输出流、Properties

节点流和处理流的区别和联系:

  1. 节点流是底层流/低级流,直接和数据源相连
  2. 处理流(包装流) 包装节点流,即可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
  3. 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源项链

处理流的功能主要体现在以下两个方面:

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
  2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

修饰器设计模式:

有一个超类,有多个子类,功能类中又有一个超类属性,这样功能类就可以使用多种子类的方法实现。并且对他们进行二次开发。

BufferedReader
public static void main(String[] args) throws IOException {
    BufferedReader bufferedReader = new BufferedReader(new FileReader("e:\\program.txt"));
    String line;//按行读取
    while ((line=bufferedReader.readLine())!=null){//当返回null时,表示读取结束
        System.out.println(line);
    }
    //注意:这里只需要关闭bufferedReader就可以了,因为底层会自动关闭节点流
    bufferedReader.close();
}
BufferedWriter
public static void main(String[] args) throws IOException {
    final FileWriter fileWriter = new FileWriter("e:\\bufferedWriterTest.txt");
    fileWriter.write("hello,BufferedWriterTest0");
    BufferedWriter bufferedWriter=new BufferedWriter(fileWriter);
    bufferedWriter.write("\n");//手动进行换行
    bufferedWriter.newLine();//根据系统不同自动输入\r或\n进行换行
    bufferedWriter.write("hello,BufferedWriterTest1");
    bufferedWriter.newLine();
    bufferedWriter.write("hello,BufferedWriterTest2");
    bufferedWriter.write("hello,BufferedWriterTest3");

    bufferedWriter.close();//关闭处理流(包装流),底层会自动关闭节点流
}
BufferedCopy
public static void main(String[] args) {
    BufferedWriter bufferedWriter=null;
    BufferedReader bufferedReader=null;
    String srcFilePath="e:\\program.txt";
    String destFilePath="e:\\program2.txt";
    try {
        bufferedReader=new BufferedReader(new FileReader(srcFilePath));
        bufferedWriter=new BufferedWriter(new FileWriter(destFilePath,true));
        String line;//BufferedRead的readLine方法会返回String类型结果
        while ((line=bufferedReader.readLine())!=null){
            bufferedWriter.write(line);
            bufferedWriter.newLine();//readLine不会读取换行符,需要手动换行
        }
    }catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bufferedReader!=null){
                bufferedReader.close();
            }
            if (bufferedWriter!=null){
                bufferedWriter.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
BUfferedCopy:
public static void main(String[] args) {
    String srcFilePath="E:\\ZZU_CSP2021Demo\\ZZU_CSP2021Demo.zip";
    String destFilePath="e:\\test.zip";
    BufferedInputStream bufferedInputStream= null;
    BufferedOutputStream bufferedOutputStream=null;
    try {
        bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
        bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(destFilePath,true));
        byte[] buf=new byte[1024];
        int readLen=0;
        while ((readLen=bufferedInputStream.read(buf))!=-1){
            bufferedOutputStream.write(buf,0,readLen);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bufferedInputStream!=null){
                bufferedInputStream.close();
            }
            if (bufferedOutputStream!=null){
                bufferedOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
对象流

将int=100 保存到文件中,注意不是100数字,而是int 100,并且能够从文件中直接恢复int 100

将Dog dog=new Dog(“小狗”,5);保存到文件中,并且能够从文件中直接恢复dog对象。

序列化和反序列化:

  1. 序列化就是在保存数据时,保存数据的值和数据类型
  2. 反序列化就是在恢复数据时,恢复数据的值和数据类型
  3. 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
    • Serializable //这是一个标记接口
    • Externalizable 这个接口有方法需要实现,一般不使用

Serializable接口源码:

public interface Serializable {
}

没有任何方法,是一个标记接口

ObjectOutputStream
public class ObjectOutputStream_ {
    public static void main(String[] args) throws Exception {
        //序列化后保存的并不是一个纯文本文件,而是一个.dat文件
        String filePath="e:\\object.dat";
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
        objectOutputStream.writeInt(100);//int会自动转换成Integer Integer实现了Serializable接口
        objectOutputStream.writeBoolean(true);
        objectOutputStream.writeDouble(8.88);
        objectOutputStream.writeChar('a');//char->Character Character实现了Serializable接口
        objectOutputStream.writeUTF("用ObjectOutputStream保存String");//String实现了Serializable接口
        objectOutputStream.writeObject(new Dog("秋田狗",5));//保存的对象类必须实现了Serializable接口
        System.out.println("保存成功");
        objectOutputStream.close();
    }
}
class Dog implements Serializable {
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
ObjectInputStream
  1. 反序列化取数据时顺序需要与序列化时一致
  2. 当序列化的类发生变化时,需要重新序列化,否则会报错
  3. dog的编译类型是Object,dog的运行类型是Dog
  4. 如果需要调用dog类的方法,需要将dog向下转型为Dog类型
public static void main(String[] args) throws IOException, ClassNotFoundException {
    String filePath="e:\\object.dat";
    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
    //读取顺序要与序列化顺序保持一致
    System.out.println(objectInputStream.readInt());
    System.out.println(objectInputStream.readBoolean());
    System.out.println(objectInputStream.readDouble());
    System.out.println(objectInputStream.readChar());
    System.out.println(objectInputStream.readUTF());
    //dog的编译类型是Object,dog的运行类型是Dog
    Object dog = objectInputStream.readObject();
    System.out.println("运行类型= "+dog.getClass());
    System.out.println("dog信息="+dog);

    objectInputStream.close();
}
对象流注意事项
  1. 读写顺序要一致
  2. 要求实现序列化或反序列化的对象,类都要实现Serializable接口
  3. 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
  4. 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的对象
  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口
  6. 序列化具有可继承性
标准输入输出流

System.in 默认设备 键盘

​ 编译类型InputStream

​ 运行类型BufferedInputStream

System.out 默认设备 显示器

​ 编译类型 PrintStream

​ 编译类型 PrintStream

public static void main(String[] args) {
    System.out.println(System.in);//编译类型为InputStream 运行类型为BufferedInputStream
    System.out.println(System.out);//编译类型为PrintStream 运行类型为PrintStream
    String text;
    Scanner scanner=new Scanner(System.in);
    System.out.println("请输入:");
    System.out.println(scanner.next());
}

修改标准输出流的输出位置:

System.setOut(new PrintStream("e:\\f1.txt"));
System.out.println("输出到e:\\f1.txt了");
转换流

默认为UTF-8,当编码不为UTF-8时,会出现乱码,此时需要使用转换流InputStreamReader(Reader的子类,可以将InputStream(字节流)包装成Reader(字符流))

OutputStreamReader(Writer的子类,可以将OutputStream包装成Writer(字符流))

可以在使用时指定编码格式(比如UTF-8,gbk,gb2312,ISO8859-1等)

public static void main(String[] args) throws IOException {
    //使用BufferedReader,当文件编码不是utf-8时,出现了乱码
    //BufferedReader bufferedReader = new BufferedReader(new FileReader("e:\\codequestion.txt"));
    //String line = bufferedReader.readLine();
    //System.out.println(line);
    //bufferedReader.close();

    //将字节流FileInputStream转换成字符流InputStreamReader
    InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("e:\\codequestion.txt"), "gbk");
    BufferedReader bufferedReader1 = new BufferedReader(inputStreamReader);
    String readLine = bufferedReader1.readLine();
    System.out.println(readLine);
    bufferedReader1.close();
}
public static void main(String[] args) throws IOException {
    String charset="gbk";
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("e:\\OutputStreamWriter.txt"), charset);
    outputStreamWriter.write("这是一个编码类型为gbk的文件");
    System.out.println("编码类型为 "+charset+"的文件");
    outputStreamWriter.close();
}
Properties类

有一个配置文件mysql.properties

ip=192.168.xx.xx

name=xxx

password=xxx

使用Properties类可以方便地解决

  1. Properties是专门用于读取配置文件的集合类

    配置文件的格式:

    键=值

    键=值

  2. 注意:键值对不需要有空格,值不需要用引号引起来。默认类型为String

  3. 常用方法:

    • load :加载配置文件的键值对到Properties对象
    • list :将数据显示到指定设备
    • getProperty(key):根据键获取值
    • setProperty(key,value):设置键值对到Properties对象
    • store:将Propertie中的键值对存储到配置文件中,在idea中,保存信息到配置文件,如果含有中文,会存储为Unicode码
public static void main(String[] args) throws IOException {
    //使用String类的split方法取得键和值
    BufferedReader br = new BufferedReader(new FileReader("src\\file\\properties\\mysql.properties"));
    String line;
    while ((line=br.readLine())!=null){
        String[] split=line.split("=");
        System.out.println(split[0]+" 的值为:"+split[1]);
    }
    br.close();
}
public static void main(String[] args) throws IOException {
    //使用Properties类
    Properties properties = new Properties();
    properties.load(new FileInputStream("src\\file\\properties\\mysql.properties"));
    properties.setProperty("database","mysql");
    System.out.println(properties.getProperty("ip"));
    properties.list(System.out);
    properties.store(new FileWriter("src\\file\\properties\\mysql1.properties"),"comments");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值