21.Java语言缓冲流、转换流、序列化反序列化、更改打印流

版权声明:原创,转载请说明,谢谢! https://blog.csdn.net/ajia5216/article/details/82793260

缓冲流

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

1.字节缓冲流:

       1).输出流:OutputStream

              |--FileOutputStream(基本流)

              |--FilterOutputStream

                     |--BufferedOutputStream(缓冲流)

       2).输入流:InputStream

              |--FileInputStream(基本流)

              |--FilterInputStream

                     |--BufferedInputStream(缓冲流)

       3).构造方法:

BufferedInputStream(InputStream in) 创建一个 BufferedInputStream对象,参数是一个输入流。InputStream是抽象

类,可以用子类对象

BufferedInputStream(Outputstream out) 创建一个 BufferedInputStream对象,参数是一个输出流。Outputstream是抽

象类,可以用子类对象

4).代码示例:

BufferedInputStream bin = new BufferedInputStream(new FileInputStream("demo.txt"));

BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("demo.txt"));

2.字符缓冲流:

       1).输出流:Writer

              |--OutputStreamWriter(转换流)

                     |--FileWriter(基本流)

              |--BufferedWriter(缓冲流)

              (特有方法:newLine():输出一个换行符)

       2).输入流:Reader

              |--InputStreamReader(转换流)

                     |--FileReader(基本流)

              |--BufferedReader(缓冲流)

               (特有方法:readLine():读取一行数据)转换流

       3).构造方法:

       BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的 缓冲字符输入流。

       BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。 

       4).代码示例:

BufferedReader bin = new BufferedReader(new FileReader("demo.txt"));

BufferedWriter bout = new BufferedWriter(new FileWriter("demo.txt"));

3.缓冲流的使用_案例_文本排序:

public static void main(String[] args) throws IOException {

    //创建输入输出的缓冲流
    BufferedReader bin = new BufferedReader(new FileReader("sort.txt"));
    BufferedWriter bout = new BufferedWriter(new                
                                                 FileWriter("sort_allright.txt"));

    //Map存放序号和对应的句子
    Map<Integer,String> stringMap = new LinkedHashMap<>();

    //用缓冲流的特有方法,一次读写一行
    String s = null ;
    while ((s = bin.readLine()) != null) {
        //分割字符串
        String[] arr = s.split("\\.");
        stringMap.put(Integer.parseInt(arr[0]), arr[1]);
    }

    //按照序号遍历Map中的内容并写出
    for (int i = 1; i < stringMap.size(); i++) {
        bout.write(i + "." + stringMap.get(i));
        bout.newLine();
    }

    //关闭资源
    bin.close();
    bout.close();
}

转换流

1.字符编码和字符集:

字符编码:

就是一套自然语言的字符与二进制数之间的对应规则。

计算机是以二进制存储,按照某种规则,将字符存储到计算机中,称为编码

将存储在计算机中的二进制数,按照某种规则解析显示出来,称为解码

字符集: 

常见的字符集(编码表):记录了字符和数字的映射关系。当计算机存储“字符”时,实际存储的是这个字符对应的数字的二进制。

       1.ASCII码表:最早的码表。记录了128个字符,每个字符使用1个字节表示。

       2.中文的码表(GBxxxx)

              1).GB2312:早期的码表,里面一共记录了7000多个汉字;现在已经不使用了。

              2).GBK : 目前使用的码表。里面一共记录了2万多个汉字,每个汉字使用2个字节表示;

              3).GB18030 : 未来要使用的码表。7万多汉字。每个汉字使用1,2,3个字节表示;

     3.UTF-8码表:国际码表。有中文;字符采用1,2,3,4字节表示。每个中文使用:3个字节表示;

     4.Unicode码表:国际码表,有中文(3,4千),每个字符使用2个字节表示。Java就是支持Unicode码表的。

              5.ISO-8859-1码表:没有中文。

编码引出的问题:

       乱码—解码与编码不一致

       例如:Windows中文系统中就是使用的GBK的编码,在IDEA中默认的字符集是UTF-8,两种编码中汉字占用的字节数不同,(UTF-8占用三个字节)读取时就会出现乱码          解决:读取时将编码转换成一致

2.转换输出流和转换输入流:

       1).转换输出流:

              构造方法:

              OutputStreamWriter(OutputStream in) : 创建一个用默认字符集的字符流。

OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流。

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
    OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("demo.txt"));
    OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("demo.txt"),"GBK");
}

2).转换输入流:

构造方法:

InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。

InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流。

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
    InputStreamReader in1 = new InputStreamReader(new FileInputStream("demo.txt"));
    InputStreamReader in2 = new InputStreamReader(new FileInputStream("demo.txt"),"GBk");
}

3.转换输入输出流使用:

IDEA默认的字符集是UTF-8,Windows默认的是GBK,为了避免乱码,使用GBK读取文档,然后用UTF-8输出

public static void main(String[] args) throws IOException {

    //创建指定字符集转换输出输入流,

    InputStreamReader in = new InputStreamReader(
                            new FileInputStream("demo.txt"),"GBK");
    OutputStreamWriter out = new OutputStreamWriter(
                            new FileOutputStream("demo_copy.txt"),"UTF-8");

    //按照字符读取
    int b = 0;
    while ((b = in.read()) != -1) {
        out.write(b);
    }
    out.close();
    in.close();
}

如果读取的输出的编码不一致就会乱码

序列化流

序列化:

指将一个“对象连同属性值”一起存储在一个文件中,或者通过网络传输,这个过程叫:序列化。

反序列化;

指将之前序列化的对象,再次读取到程序中,并在内存中创建对象。

1.序列化流ObjectOutputStream类;

       构造方法:

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

注意:被序列化的对象必须实现:java.io.Serializable(接口)

         此接口无任何抽象方法,这种接口叫:标记接口,表示开启了某些功能。

public static void main(String[] args) throws IOException {
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_Student.txt"));
    out.writeObject(new Student(1,"张三","男",23));
    out.close();
}

2.反序列化ObjectInputStream类:

       构造方法:

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

       注意:接收的Student必须是之前“序列化时”的那个包下的Student类型,不能是其它包下的,否则运行时异常。它必须是能够找到class文件的类

public static void main(String[] args) throws IOException, ClassNotFoundException {

    ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_Student.txt"));

    //返回Object类型
    Student stu = (Student) in.readObject();
    System.out.println(stu);
    in.close();
}

3.版本号:

       Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

例如:private static final long serialVersionUID = 2;

如果没有给定序列号,如果修改了序列化的类,再次反序列化的时候(没有再次序列化)就会抛异常,因为序列号不一样了,如果给定了序列号,则不会抛异常

4.禁止属性被序列化transient关键字

       用transient关键字修饰属性,在序列化时该苏醒不会被序列化

当一个属性被transient修饰,反序列化出来的值时属性的默认值

1       张三       男       0//年龄属性被禁止序列化,输出为0

5.序列化的使用_序列化集合:

 
public static void main(String[] args) throws IOException, ClassNotFoundException {

    //创建序列化的集合并初始化数据
    ArrayList<Student> stuList = new ArrayList<>();
    stuList.add(new Student(1,"张三","男",19));
    stuList.add(new Student(2,"张四","女",20));
    stuList.add(new Student(3,"张五","男",21));
    stuList.add(new Student(4,"张六","女",22));

    //创建序列化输出流和反序列化输入流
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_xuliehuajihe.txt"));
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_xuliehuajihe.txt"));

    //序列化集合
    out.writeObject(stuList);

    //关闭资源
    out.close();

    //反序列化集合,并接受返回的集合
    ArrayList<Student> studentList = (ArrayList<Student>) in.readObject();

    //遍历输出反序列化返回的数据
    for (Student student : studentList) {
        System.out.println(student);
    }
    in.close();

}

 

打印流

1.字节打印流PrintStream类

       构造方法:

       public PrintStream(String fileName) 使用指定的文件名创建一个新的打印流。

2.改变打印流的方向:

System.out.println():向控制台输出数据,System.out就是:PrintStream类型;默认被指向:控制台,想改变打印的方向,改变这个out就行

注意:

       Out是System类的一个成员属性,所以可以用get/set方法访问

输出方法和控制台一样

使用示例:

public static void main(String[] args) throws FileNotFoundException {
    PrintStream ps = new PrintStream("demo.txt");
    System.setOut(ps);
    System.out.println("呵呵");
}

 

猜你喜欢

转载自blog.csdn.net/ajia5216/article/details/82793260
今日推荐