IO之处理流、打印流

处理流

  • 处理流(也叫包装流)是连接已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能;如:BufferedReader、BufferedWriter

  • BufferedReader、BufferedWriter类中有对应的Reader、Writer的属性,使其可以对Reader、Writer及其任意子类进行操作

字符处理流

BufferedReader

主要用于辅助Reader及其任何子类的字符输入流,它带有缓冲区,可以先将一批数据读到内存缓冲区。后续操作就可以直接从缓冲区获取数据,而不需要每次都从数据源读取数据并进行字符编码转换,从而提高数据的读取效率。关闭处理流时,只需关闭外层流即可,底层会自动关闭;需抛出异常

  • 构造方法:

    • BufferedReader(Reader in ):创建一个对象来修饰参数in指定的字符输入流;

    • BufferedReader(Reader in ,int size):创建一个对象来修饰参数in指定的字符输入流,参数size指定缓冲区的大小,单位为字符;

  • BufferedReader还提供了readLine()方法,该方法返回包含该行内容的字符串,但该字符串中不包含任何终止符,如果到达流末尾,返回null。该方法表示每次读取一行文本内容,遇到换行(\n)、回车(\r)、或回车后直接跟着换行标记符,即认为此行已终止。

        String filePath = "E:\\Desktop\\新建文本文档.txt";
       //创建处理流对象,需抛出异常
       BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
       //读取
       String line ;//按行读取
       while ((line = bufferedReader.readLine())!= null ){
           System.out.println(line);
      }
       //关闭流,这里只需关闭BufferedReader,因为底层会自动关闭
       bufferedReader.close();

BufferedWriter

主要用于辅助Writer及其任意子类的字符输出流,它带有缓冲区,可以先将一批数据写入内存缓冲区,当缓冲区满了以后,再将缓冲区的数据一次性写到字符输出流,目的是提高数据的写入效率。

  • 构造方法:

    • BufferedWriter(Writer out):创建一个对象来修饰参数in指定的字符输出流;

    • BufferedWriter(Writer out,int size):创建一个对象来修饰参数in指定的字符输出流,参数size指定缓冲区的大小,单位为字符;

  • BufferedWriter还提供了一个新的方法newLine(),该方法用于写入一个行分隔符。行分割符字符串由系统属性line.separator定义,并且不一定是单个新行(\n)符;

        String filePath = "e:\\z_practice\\test.txt";
       //如需要以追加的方式写入,在构造器中加true;创建处理流对象,需抛出异常
       BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
       bufferedWriter.write("hello111,知足常乐" + "\n");//插入换行
       bufferedWriter.write("hello1,知足常乐");
       bufferedWriter.newLine();//插入系统相关的换行符
       bufferedWriter.write("hello2,知足常乐");
       //关闭流
       bufferedWriter.close();

利用BufferedReader和BufferedWriter拷贝文件,不能操作二进制文件,否则复制的文件显示损坏

字节处理流

  • BufferedInputStream和BufferedOutputStream;参考字符处理流

  • 用于操作二进制文件,同时也可以操作文本文件;

对象流

  • 序列化和反序列化

  • 序列化就是在保存数据时,保存数据的值和数据类型

  • 反序列化就是在恢复数据时,恢复数据的值和数据类型

  • 需要让某个对象支持序列化机制,则必须让其类是可序列化的,即此类必须实现Serializable接口、Externalizable接口之一;

    • Serializable,是一个标记接口,内部没有方法

    • Externalizable,该接口有方法需要实现,一般实现标记接口

  • 八大基本类型会自动装箱,其包装类及String类已实现Serializable

  • 当使用对象流写入或读入对象时,要保证对象是序列化的,这是为了保证能把对象写入到文件,并能再把对象正确的读取回到程序中;


  • ObjectOutPutStream:对象输出流,提供序列化功能;使用writeObject(Object,obj)将obj写入到一个文件中;实现了ObjectOutPut接口、OutputStream抽象类;

  • ObjectInputStream:对象输入流,提供反序列化功能;使用readObject()读取一个对象到程序中;实现了ObjectInPu接口t、InputStream抽象类;


  • 构造方法:

    • ObjectInputStream(InputStream in);

    • ObjectOutPutStream(OutputStream out);

  • 对象流的指向应当是一个输入/出流,因此当准备将一个文件写入/读取时,首先创建一个输入/出流;

        //序列化对象,数据写入文件
//序列化后,保存格式不是纯文本,根据对象的格式确定
       String outPath = "e:\\z_practice\\object.txt";
       ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outPath));//抛出异常
       oos.writeInt(100);
       oos.writeBoolean(true);
       oos.writeChar('a');
       oos.writeChars("天天向上");//字符串
       oos.writeDouble(100.124);
       oos.writeUTF("卷不动,躺不平");//字符串

       oos.writeObject(new Dog("柯基", 3));//Dog类需实现序列化接口
       oos.close();
class Dog implements Serializable {}
        //反序列化,读取文件到程序
//声明需反序列化的文件
String inPath = "e:\\z_practice\\object.dat";
      ObjectInputStream ois = new ObjectInputStream(new FileInputStream(inPath));
       System.out.println(ois.readInt());//读取Integer
       System.out.println(ois.readBoolean());//读取Boolean
       System.out.println(ois.readChar());//读取字符
       //System.out.println(ois.readChar());//读取字符串
       System.out.println(ois.readDouble());//读取Double
       System.out.println(ois.readUTF());//读取字符串
       Object dog = ois.readObject();//需抛出类型转换异常ClassNotFoundException
       System.out.println(dog.toString());

       //重要提醒:如果希望调用对象dog的方法,需要向下转型
       //对象输出流和对象输入流同包可直接转型,不同包需要将Dog类的定义拷贝到引用的地方,或者将Dog设置为public类,并导包
       Dog dog1 = (Dog)dog;
       System.out.println(dog1.getName());
       ois.close();//关闭对象输入流

注意事项:

  1. 读写顺序要一致,避免类型异常

  2. 序列化和反序列化的对象,必须实现serializable接口;

  3. 序列化的类中建议添加serialVersionUID表示当前类的序列版本信息,为了提高版本的兼容性;

  4. 序列化对象时,默认将里面所有属性都进行序列化,但static、transient成员除外;

  5. 序列化对象时,要求里面属性的类型也实现序列化接口;

  6. 序列化具备可继承性,即某类实现了序列化,其所有子类默认实现了序列化;

转换流

  • 正常情况下,字节流可以对所有的数据进行操作,但有时候在处理一些文本时需要用到字符流。所以Java中IO流提供了两种用于将字节流转换为字符流的转换流;

  • 转换流可以在一定程度上避免乱码,读取文件和写入文件时的编码要和文件的编码形式对应;

  • InputStreamReader用于将字节输入流包装为字符输入流,是Reader的子类;存在多种构造器,可以传入InputStream,指定编码方式;详见类图

  • OutputStreamWriter用于将字节输出流包装为字符输出流,是Writer的子类;同上

  • 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文乱码问题,建议将字节流转换成字符流;

  • 可以在使用时指定编码格式(如:ASCII、utf-8,gbk,gb2312,ISO8859-1等);


使用:将字节(输出/输入)流包装成字符(输出/输入)流并指明编码格式,再将转换流包装成对象流;


标准输入、输出流

 编译类型运行类型默认设备
System.in InputStream BufferedInputStream 键盘
System.out PrintStream PrintStream 显示器

Print打印流

打印流没有输入流,只有输出流

  • PrintStream:字节流,是OutputStream的子类;

    • 默认情况下,输出数据的位置是标准输出,即显示器;可以根据需求修改打印流输出的位置;

  • PrintWriter:字符类,是Writer的子类;具有多种构造器,详见API

        //字节流
PrintStream printStream = new PrintStream("e:\\z_practice\\printStream.txt");
       printStream.println("三国志7000万人");//方式一
       System.setOut(new PrintStream(printStream));//方式二:修改system的默认显示器到文件
       System.out.println("三国志7000万人");
       printStream.close();
     
//字符流
PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\z_practice\\printWriter.txt"));
       printWriter.write("爪哇岛");
       printWriter.close();//需关闭流

Properties类

  • Properties是HashTable的子类;

  • 专门用于读写配置文件的集合类;配置文件格式:键=值 键=值

  • 注意:键值对不需要有空格,值不需要用引号括起来,默认是String类型;

  • Properties常用方法:

    1. load:加载配置文件的键值对到Properties对象;

    2. list:将数据显示到指定设备、文件、流;

    3. getProperty(key):根据键获取值;

    4. setProperty(key,value):设置键值对到Properties对象;有key是修改,没有是添加

    5. store(writer/outputstream , null):将将Properties中的键值对存储到配置文件;在java中,保存信息到配置文件,如果含有中文,会存储为Unicode码;此处null为注解部分,可自行设置

posted @ 2022-08-24 20:31  许多多被注册了  阅读(40)  评论(0编辑  收藏  举报