java基础之--缓冲流-字节流+字符流+转换流+序列化+打印流

昨天学习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流。比如能够高效读写的缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化流等等。这些功能更为强大的流,都是在基本的流对象基础之上创建而来的,就像穿上铠甲的武士一样,相当于是对基本流对象的一种增强

1. 概述

缓冲流,也叫高效流 ,是对4个基本的FileXxx流的增强,所以也是4个流,按照数据类型分类

  • 字节缓冲流: BufferedInputStreamBufferedOutputStream
  • 字符缓冲流: BufferedReaderBufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

2. 字节缓冲流

构造方法

  • public BufferedInputStream(InputStream in) : 创建一个新的缓冲输入流
  • public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流
package Stream;

import FileStream.FileOutputStreamConstructor;

import java.io.*;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 14:28
 */
public class BufferDemo {
    public static void main(String[] args) throws Exception {
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\softWare-all\\developSoftware\\projectPath\\java-project\\Thread\\src\\Stream\\wegameservice.exe"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
            int len;

            byte[] bytes = new byte[8*1024];
            while ((len = bis.read(bytes)) != -1){
                bos.write(bytes,0,len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        // 记录结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("缓冲流使用数组复制时间: "+(endTime-startTime) + "毫秒");

    }
}

3. 字符缓冲流

  • public BufferedReader(Reader in) : 创建一个新的缓冲输入流
  • public BufferedWriter(Writer out) : 创建一个新的缓冲输出流

字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法

  • BufferedReader: public String readLine() : 读一行文字
  • BufferedWriter: public void newLine() : 写一行行分隔符,由系统属性定义符号

readline方法演示

package Stream;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 15:17
 */
public class BufferReaderDemo {
    public static void main(String[] args) throws Exception {
        // 创建流对象
        BufferedReader br = new BufferedReader(new FileReader("fw.txt"));

        String line = null;
        while ((line = br.readLine()) != null){
            System.out.println(line);
            System.out.println("--------------------------");
        }

        br.close();
    }
}

newLine方法演示

package Stream;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 15:20
 */
public class BufferWriterDemo {
    public static void main(String[] args) throws IOException {
        // 创建流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("fw.txt"));

        bw.write("宁宁小可爱");
        bw.newLine();
        bw.write("新年快乐");

        bw.close();
    }
}
输出结果:
宁宁小可爱
新年快乐

4. 转换流

字符集 Charset :是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。 计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符 集有ASCII字符集、GBK字符集、Unicode字符集等,可见,当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的

在这里插入图片描述
在IDEA中,使用 FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的 UTF-8 编码,所以没有任何问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码,那么如何读取GBK编码的文件呢

4.1 InputStreamReader类

构造方法

  • InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流
  • InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流

指定编码读取

package Stream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 15:29
 */
public class ReadDemo {
    public static void main(String[] args) throws Exception {
        String filePath = "E:\\test.txt";
        // 创建流对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath));
        // 创建流对象 指定编码GBK
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream(filePath));

        int read;

        while ((read = isr.read()) != -1){
            System.out.println((char)read);
        }
        isr.close();
        while ((read = isr2.read()) != -1){
            System.out.println((char)read);
        }
        isr2.close();
    }
}

输出结果: isr乱码 isr2 输出如下
新
年
快
乐
宁
宁
小
可
爱

4.2 OutputStreamWriter类

转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集讲字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集

构造方法

  • OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流
  • OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流

指定编码

package Stream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 15:40
 */
public class OutPutDemo {
    public static void main(String[] args) throws IOException {
        String filePath = "E:\\test.txt";
        // 创建流对象,默认UTF-8编码
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath));

        // 写数据
        osw.write("宁宁小可爱");
        osw.close();


        String filePath2 = "E:\\test2.txt";
        // 创建流对象,默认UTF-8编码
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(filePath2),"GBK");

        // 写数据
        osw2.write("宁宁小可爱");
        osw2.close();
    }
}

转换流图解

在这里插入图片描述

5. 序列化

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据 、 对象的类型和对象中存储的数据等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。 对象的数据 、 对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象

在这里插入图片描述

5.1 ObjectOutputStream类

java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储

构造方法

  • public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream

序列化操作,一个对象要想序列化,必须满足两个条件

  • 该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出 NotSerializableException
  • 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰
package Stream;

import sun.management.Agent;

import java.io.Serializable;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 15:55
 */
public class Employee implements Serializable {
    public String name;
    public String address;
    public transient  int age; // transient瞬态修饰成员,不会被序列化
}

写出对象方法

  • public final void writeObject (Object obj) : 将指定的对象写出
package Stream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 15:58
 */
public class SerializeDemo {
    public static void main(String[] args)  {
        Employee e = new Employee();
        e.name = "ningning";
        e.address = "beijing";
        e.age = 19;

        try {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.txt"));
            out.writeObject(e);
            out.close();
            System.out.println("Serialized data is saved");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

5.2 ObjectInputStream类

ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象

构造方法

  • public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream

反序列化操作

如果能找到一个对象的class文件,我们可以进行反序列化操作,调用 ObjectInputStream 读取对象的方法

  • public final Object readObject () : 读取一个对象
package Stream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 16:04
 */
public class DeSerializeDemo {
    public static void main(String[] args) {
        Employee e = null;

        try {
            // 创建反序列化流
            FileInputStream fis = new FileInputStream("employee.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);

            // 读取对象
            e = (Employee)ois.readObject();
            ois.close();
            fis.close();

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        System.out.println("name : "+e.name);
        System.out.println("address : "+e.address);
        System.out.println("address : "+e.age);
    }
}

6. 打印流- PrintStream类

平时我们在控制台打印输出,是调用 print 方法和 println 方法完成的,这两个方法都来自于 java.io.PrintStream 类,该类能够方便地打印各种数据类型的值,是一种便捷的输出方式

构造方法

  • public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流
  • 举例如下
PrintStream ps = new PrintStream("test.txt")

改变打印流向
System.out 就是 PrintStream 类型的,只不过它的流向是系统规定的,打印在控制台上。不过,既然是流对象, 我们就可以玩一个"小把戏",改变它的流向

package Stream;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-16 16:11
 */
public class PrintDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 控制台输出 97
        System.out.println(97);
        // 创建打印流 指定文件名称
        PrintStream ps = new PrintStream("ps.txt");
        // 设置流向 输出到ps.txt
        System.setOut(ps);

        // 再次打印97
        System.out.println(97);
    }
}

发布了41 篇原创文章 · 获赞 1 · 访问量 3566
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 黑客帝国 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览