缓冲流、转换流、序列化流、打印流

缓冲流

缓冲流也叫高效流,是对四个基本的FileXXX流的增强,按照数据类型分类:
字节缓冲流:BufferedInputStream,BufferedOutputStream
字符缓冲流:BufferedReader,BufferedWritter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过对缓冲取=区读写,减少系统IO次数,从而提高读写效率

字节缓冲流

构造方法:
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
参数:
OutputStream out:字节输出流
我们可以传递FileOutputStream,缓冲流会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率
int size:指定缓冲流内部缓冲区的大小,不指定默认

package FileBufferDemo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class BufferInputStream {
    public static void main(String[] args) throws IOException {
        //1、创建FileInputStream对象,构造方法中绑定要读取的数据源
        FileInputStream fis = new FileInputStream("D:\\a.txt");
        //2、创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象效率
        BufferedInputStream bos = new BufferedInputStream(fis);
        //3、使用BufferedInputStream对象中方法read,读取文件

        /*int len=0;
        while ((len =bos.read())!=-1){
            System.out.println(len);
        }*/
       byte[] bytes =new byte[1024];
       int len =0;
       while ((len=bos.read(bytes))!=-1){
           System.out.println(new String(bytes,0,len));
       }

        bos.close();
    }
}

字符缓冲流

构造方法
public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。
特有方法
字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法。
BufferedReader: public String readLine() : 读一行文字。
BufferedWriter: public void newLine() : 写一行行分隔符,由系统属性定义符号。

package FileBufferDemo;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferOutputStream {
    public static void main(String[] args) throws IOException {
        //1、创建FileOutputStream对象,构造方法中绑定要输出的目的地
        FileOutputStream fos = new FileOutputStream("D://a.txt");
        //2、创建BufferefOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream对象效率
        BufferedOutputStream bos =new BufferedOutputStream(fos);
        //3、使用BufferedOutputStream对象中的方法write,把数据写入到内存缓冲区中
        bos.write("我把数据写入到内存缓冲区".getBytes());
        bos.flush();
        bos.close();

    }
}

package FileBufferDemo;

import java.io.*;

public class BufferedReaderAndWriter {
    public static void main(String[] args) throws IOException {
        //BufferedWriter
        //1、创建字符缓冲流输出流对象,构造方法中传递字符输出流
        //BufferedWriter bw= new BufferedWriter(new FileWriter("D:\\a.txt"));
        //2、调用字符输出流中的write方法,把数据写入到内存缓冲区
     /*   for (int i = 0; i < 4; i++) {
            bw.write("传智播客");
            //void newLine() 写入一个行分隔符,会根据不同的操作系统,获取不同的行分隔符
            bw.newLine();//等效于bd.write(“\r\n”)
        }
        bw.flush();
        bw.close();*/

        //BufferedReader
        //1、创建字符缓冲输入流对象,构造方法中传递字符输入流
        BufferedReader bd= new BufferedReader(new FileReader("D://a.txt"));
        //2.使用字符缓冲输入流对象中的方法read/readLine读取文本
        /*String readLine()//读取一个文本行 读取一行数据
        行的终止符号:通过下列字符之一即可认为某行已终止:
            换行(“\n”)、回车(“\n")或回车后直接跟着换行(“\r\n”)
           返回值:
           包含该行内容的字符串,不包含任何终止符,如果已达到流末尾,则返回null
        */
        String line;
        while ((line=bd.readLine())!=null){
            System.out.println(line);
        }

    }
}

package FileBufferDemo;

/*练习:
对文本的内容进行排序,按照(1,2,3....)顺序排序
分析:
1、创建一个HashMap集合对象,可以:存储每行文本的序号(1.2.3,...),value存储每行的文本
2、创建字符缓冲输入流对象,构造方法中绑定字符输入流
3、创建字符缓冲输出流对象,构造方法中绑定字符输出流
4、使用字符缓冲输入流中的方法readLine,逐行读取文本
5、把读取的文本进行切割,获取行中的序号和文本内容
6、把切割好的序号和文本的内容存储到HashMap集合中(key序号是有序的,会自动排序1,2,3...)
7、遍历HashMap集合,获取每一个键值对
8、把每一个键值对,拼接成为一个文本行
9、把拼接好的文本,使用字符缓冲输出流中的方法write,写入到文本中
10、释放资源
*/

import java.io.*;
import java.util.HashMap;

public class BufferedExerciseDemo {
    public static void main(String[] args) throws IOException {
        HashMap<String,String> map = new HashMap<>();
        BufferedReader br = new BufferedReader(new FileReader("D:\\abc.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\B.TXT"));
        String line;

        while ((line=br.readLine())!=null){
            String[] arr=line.split("\\.");
            map.put(arr[0],arr[1]);
        }
        for(String key:map.keySet()){
            String value =map.get(key);
            line=key+"."+value;
            bw.write(line);
            bw.newLine();
        }
        bw.close();
        br.close();
    }
}

package FileBufferDemo;
/*
文件复制练习二:
   明确:
   数据源:D://me.jpg
   数据目的地:C://me.jpg
 文件复制的步骤:
 1、创建一个字节缓冲输入流对象,构造方法中传递字节输入流
 2、创建一个字节缓冲输出流对象,构造方法中传递字节输出流
 3、使用字节缓冲输入流对象中的方法read读取文件
 4、使用字节缓冲输出流对象中write方法,把读取的数据写入到内存缓冲区中
 5、释放资源(会先把缓冲区中的数据刷新到文件中)
*/

import java.io.*;

public class BufferedCopyExercised {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        BufferedInputStream br =new BufferedInputStream(new FileInputStream("D:\\me.jpg"));
        BufferedOutputStream bw =new BufferedOutputStream(new FileOutputStream("F:\\me.jpg"));
        byte[] bytes =new byte[1024];
        int len=0;
        while ((len=br.read(bytes))!=-1){
            bw.write(bytes,0,len);
        }
        bw.flush();
        bw.close();
        long end =System.currentTimeMillis();
        System.out.println("总共花费:"+(end=start));

    }
}

转换流

字符编码和字符集

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制
数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码 。反之,将存储在计算机中的二进制数按照
某种规则解析显示出来,称为解码 。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本f符
号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。
字符编码Character Encoding : 就是一套自然语言的字符与二进制数之间的对应规则。

字符集

字符集 Charset :也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符
号、数字等。
计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符
集有ASCII字符集、GBK字符集、Unicode字符集等。

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

import sun.audio.NativeAudioStream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileBianMaDemo {
    public static void main(String[] args) throws IOException {
        //定义文件路径,文件UTF-8编码
        String fileName ="D:\\file_gbk.txt";
        //创建流对象,默认为UTF-8编码
        InputStreamReader ie=new InputStreamReader(new FileInputStream(fileName));
        //创建流对象,指定GBK编码
        InputStreamReader ie1 =new InputStreamReader(new FileInputStream(fileName),"GBK");
        //定义变量,保存字符
        int len =0;
        while ((len =ie1.read())!=-1){
            System.out.println((char)len);
        }
        ie.close();
    }
}

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

public class FileBianMaDemo1 {
    public static void main(String[] args) throws IOException {
        //定义文件路径
        String fileName = "D:\\b.txt";
        //创建流对象,默认为UTF8编码
        OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(fileName));
        //创建流对象,指定GBK编码
        OutputStreamWriter ow1 = new OutputStreamWriter(new FileOutputStream("D:\\c.txt"),"GBK");

        //写出数据
        ow.write("你好");//保存为6个字节
        ow1.write("你好");//保存为4个字节
        ow1.flush();
        ow1.close();
    }
}

/*练习:1、指定GBK编码转换流,读取文本文件
2、使用UTF-8编码转换流,写出文本文件
*/

import java.io.*;

public class FileBianMaDemo02 {
    public static void main(String[] args) throws IOException {
        String srcFile ="D:\\file_gbk.txt";
        String dstFile ="D:\\file_utf8.txt";
        //创建流对象
        //2.1转换输入流,指定gbk编码
        InputStreamReader isr= new InputStreamReader(new FileInputStream(srcFile),"GBK");

        //2.2转换输出流,默认utf8编码
        OutputStreamWriter dst = new OutputStreamWriter(new FileOutputStream(dstFile));
        //3、读写数据
        //3.1定义数组
        char[] chars =new char[1024];
        int len =0;
        while ((len=isr.read(chars))!=-1){
            dst.write(chars,0,len);
        }
        isr.close();
        dst.close();

    }
}

序列化

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

package SerializableDemo;

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

public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //1、创建ObjectOutputStream对象,构造方法中传递字节输出流
        ObjectOutputStream oo= new ObjectOutputStream(new FileOutputStream("D:\\d.txt"));
        //2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
        oo.writeObject(new Person("小美女",19));
        //3、释放资源
        oo.close();
    }
}

package SerializableDemo;

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private  int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

package SerializableDemo;

import java.io.*;

public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1、创建ObjectOutputStream对象,构造方法中传递字节输出流
        ObjectInputStream oo= new ObjectInputStream(new FileInputStream("D:\\d.txt"));
        //2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
        Object o = oo.readObject();
        //3、释放资源
        oo.close();
        //4、使用读取出来的对象打印
        System.out.println(o);
        Person person=(Person)o;
        System.out.println(((Person) o).getName()+":"+((Person) o).getAge());
    }
}

ps:
当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操
作也会失败,抛出一个InvalidClassException 异常。发生这个异常的原因如下:
该类的序列版本号与从流中读取的类描述符的版本号不匹配
该类包含未知数据类型
该类没有可访问的无参数构造方法
Serializable 接口给需要序列化的类:
eg:

public class Person implements Serializable {}
package SerializableDemo;
/*
练习:序列化集合
当我们想在多个对象中保存集合的时候,可以把多个对象存储到一个集合中
对集合进行序列化和反序列化

分析:
1、定义一个存储person对象的ArrayList集合
2、往集合中存储person对象
3、创建一个序列化流ObjectOutputStream对象
4、使用ObjectOutputStream对象writeObject,对集合进行序列化
5、创建一个反系列化流InputStream对象
6、使用ObjecyInputStream对象readObject,读取文件中保存的集合
7、把Object类集合转换为ArrayList类型
8、遍历ArrayList集合
9、释放资源
*/


import java.io.*;
import java.util.ArrayList;

public class ObjectSerializableExercise {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ArrayList<Person> list =new ArrayList<>();
        list.add(new Person("张三",18));
        list.add(new Person("李四",19));
        list.add(new Person("王五",20));
        ObjectOutputStream oo =new ObjectOutputStream(new FileOutputStream("D:\\e.txt"));
        oo.writeObject(list);
        ObjectInputStream oi = new ObjectInputStream(new FileInputStream("D:\\e.txt"));
        Object O =oi.readObject();
        ArrayList<Person> list1 =(ArrayList<Person>)O;
        for (Person p:list1){
            System.out.println(p.getName()+":"+p.getAge());
        }
        oo.close();
        oi.close();

    }
}

打印流

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

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

public class PrintStreamDemo {
    public static void main(String[] args) throws FileNotFoundException {
        //创建打印流PrintStream对象,构造方法中绑定要输出的目的地
        PrintStream ps = new PrintStream("D:\\f.txt");
        //如果使用继承自父类的write方法写数据,那么查看数据的时候会查询编码表97->a
        //ps.write(97);
        //如果使用自己特有的方法print/println方法写数据,写的数据原样输出97
        ps.println(97);
        ps.println(true);
        ps.close();
    }
}

/*可以改变输出语句目的地(打印流流向)
输出语句默认在控制太输出
使用System.setOut方法改变输出语句目的地 改为参数中传递的打印流的目的地
  static void setOut(PrintStream out)

*/

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

public class PrintStreamDemo01 {
    public static void main(String[] args) throws FileNotFoundException {
        int a=1;
        int b=2;
        System.out.println("我是在系统输出");
        //创建打印流 指定文件名称
        PrintStream ps = new PrintStream("D:\\e.txt");
        //设置系统的打印流流向,输出到e.txt
        System.setOut(ps);
        System.out.println(97);

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值