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

一、缓冲流

    1、缓冲流:

        字节输入缓冲流: BufferedInputStream

        字节输出缓冲流: BufferedOutputStream

        字符输入缓冲流: BufferedReader

        字符输出缓冲流: BufferedWriter

    缓冲流的特点是快,可以提高读写的效率,原因是因为内部具有一个缓冲区。

    其实缓冲流本身并不具备读或者写的功能,他真正的作用是给其他流提供加速。

    使用步骤:

        1. 创建缓冲流对象

        2. 调用read方法读取或者调用write方法写数据。(读取和写数据的方法和我们之前学的一模一样)

        3. 释放资源。

    字节缓冲流的构造方法:

    BufferedInputStream(InputStream in): 参数需要传递一个字节输入流。

    BufferedOutputStream(OutputStream out):参数需要传递一个字节输出流。

    和之前创建对象的区别: 之前构造方法位置可以直接传递字符串,现在要传递一个流对象。

public class Demo02BufferedStream {

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

        //创建字节输入缓冲流对象,用来读取

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10\\aa.jpg"));

        //创建字节输出缓冲流,用来写

        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10\\bb.jpg"));

 

        long start = System.currentTimeMillis();

 

        //开始读写,每使用缓冲输入流读取一个字节,那么就将读取到的字节写到目的地中。

        int i; //定义变量,用来接收读取到的字节

        while((i = bis.read()) != -1) {

            //将读取到的字节写到目的地中

            bos.write(i);

        }

 

        long end = System.currentTimeMillis();

        System.out.println(end - start);

 

        //释放资源

        bos.close();

        bis.close();

 

    }

}

2、  使用字节缓冲流一次读写一个字节数组的方式复制文件

 

public class Demo03BufferedStream {

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

        //创建字节输入缓冲流,用来读取

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10\\aa.jpg"));

        //创建字节输出缓冲流,用来写

        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10\\bb.jpg"));

 

        long start = System.currentTimeMillis();

 

        //开始读写,一次读写一个字节数组

        byte[] bArr = new byte[1024 * 8];

        int len;

        while ((len = bis.read(bArr)) != -1) {

            //将读取到的内容写入到目的地文件中

            bos.write(bArr, 0, len);

        }

        long end = System.currentTimeMillis();

        System.out.println(end - start);

 

        //释放资源

        bos.close();

        bis.close();

    }

}

 

3、字符缓冲流:

        字符输入缓冲流: BufferedReader

        字符输出缓冲流: BufferedWriter

    使用步骤:

        1. 创建缓冲流对象

        2. 调用read读取或者调用write写数据。读取或者写的方法和之前学的一模一样

        3. 释放资源。

 

    BufferedReader构造方法:

        BufferedReader(Reader in): 构造方法需要传递一个字符输入流。

    BufferedWriter构造方法:

        BufferedWriter(Writer out):构造方法需要传递一个字符输出流。

public class Demo01BufferedStream {

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

        method2();

    }

 

    //BufferedReader的使用

    public static void method2() throws IOException {

        //创建BufferedReader对象

        BufferedReader br = new BufferedReader(new FileReader("day10\\file02.txt"));

        //开始读取

        //一次读取一个字符

        /*

        int i;

        while((i = br.read()) != -1) {

            //把读取到的内容进行打印

            System.out.print((char)i);

        }

        */

        //一次读取一个字符数组

        int len;

        char[] cArr = new char[1024];

        while ((len = br.read(cArr)) != -1) {

            System.out.print(new String(cArr, 0, len));

        }

 

        //释放资源

        br.close();

    }

 

    //BufferedWriter的使用

    public static void method1() throws IOException {

        //创建一个BufferedWriter对象

        BufferedWriter bw = new BufferedWriter(new FileWriter("day10\\file02.txt"));

        //调用方法,写数据

        bw.write("你好");

        //释放资源

        bw.close();

    }

}

4、字符缓冲流中的特殊作用:

        BufferedWriter里面有一个方法,叫做newLine,可以实现一个跨平台的换行

        void newLine(): 写一个跨平台换行

        BufferedReader里面有一个方法,叫做readLine,可以一次读取一行数据。

        String readLine() 读一行数据。 并且把读取到的数据返回。  如果读取结束返回 null。

        注意readLine方法不会读取换行符,只会读取换行符之前的内容.

 

public class Demo02BufferedStream {

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

        method2();

    }

 

    //String readLine() 读一行数据。 并且把读取到的数据返回。  如果读取结束返回 null。

    public static void method2() throws IOException {

        //创建一个BufferedReader对象

        BufferedReader br = new BufferedReader(new FileReader("day10\\file03.txt"));

 

        //使用循环一次读取一行数据

 

        //定义变量,用来保存读取到的这行数据

        String line;

 

        //使用循环读取

        while ((line = br.readLine()) != null) {

            /*

                条件位置做了以下事情

                1. 调用readLine方法,读取一行数据

                2. 将读取到的数据赋值给变量line

                3. 判断变量line的数据是否为null,如果不是null表示读取到了数据,那么就处理

             */

            System.out.println(line);

        }

 

        /*

        //调用readLine,一次读取一行数据

        String line = br.readLine();

        System.out.println(line); //床前明月光

 

        line = br.readLine();

        System.out.println(line); //疑是地上霜

 

        line = br.readLine();

        System.out.println(line); //null

        */

        //释放资源

        br.close();

    }

 

    //void newLine(): 写一个跨平台换行

    public static void method1() throws IOException {

        //创建BufferedWriter对象

        BufferedWriter bw = new BufferedWriter(new FileWriter("day10\\file03.txt"));

        //调用write方法写数据

        bw.write("床前明月光");

        bw.newLine();//跨平台的换行

        bw.write("疑是地上霜");

 

        //释放资源

        bw.close();

    }

}

5、将出师表.txt中的内容恢复顺序,然后写入到一个新的文件中。

    出师表.txt中的内容特点:

        1. 每一行数据都是  序号.课文内容

        2. 序号是不重复

    思路:

        1. 定义一个Map集合,key是序号,value是课文内容。

        2. 创建BufferedReader对象,用来读取

        3. 读取文件中的内容,一次读取一行数据。

        4. 将读取到的这行数据使用. 切割,得到这行数据的序号以及课文内容。

        5. 将读取到的序号和课文内容放入到Map集合中。

        6. 关闭输入流。

        7. 创建一个BufferedWriter,用来写

        8. 使用for循环手动走一遍1-9.(其实就是文件中的序号, 也是Map集合中的key)

        9. 去Map集合中根据这个key拿到对应的value

        10. 将key和value使用. 进行分割重新写入到新的文件中

        11. 换行

        12. 刷新

        13. 释放资源

public class Demo03BufferedStreamTest {

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

        //定义一个Map集合,key是序号,value是课文内容。

        Map<Integer, String> map = new HashMap<>();

        //创建BufferedReader对象,用来读取

        BufferedReader br = new BufferedReader(new FileReader("day10\\出师表.txt"));

        //读取文件中的内容,一次读取一行数据。

        String line;

        while ((line = br.readLine()) != null) {

            //line中保存了读取到的数据,我们要使用.进行切割得到对应的序号以及课文内容

            //split方法是在根据正则表达式切割, .是正则表达式中的特殊字符,需要进行转义

            //strArr[0] 是序号,  strArr[1] 是课文内容

            String[] strArr = line.split("\\.");

            //将读取到的序号和课文内容放入到Map集合中

            Integer id = Integer.parseInt(strArr[0]);

            map.put(id, strArr[1]);

        }

        //关闭输入流。

        br.close();

 

        //创建一个BufferedWriter,用来写

        BufferedWriter bw = new BufferedWriter(new FileWriter("day10\\outTeacherTable.txt"));

        //使用for循环手动走一遍1-9.(其实就是文件中的序号, 也是Map集合中的key)

        for(int i = 1; i <= map.size(); i++) {

            //去Map集合中根据这个key拿到对应的value

            String content = map.get(i);

            //将key和value使用 . 进行分割重新写入到新的文件中

            bw.write(i + "." + content);

            //换行

            bw.newLine();

            //刷新

            bw.flush();

        }

        //释放资源

        bw.close();

    }

}

 

二、转换流

1、InputStreamReader表示转换流。 用来读, 可以将文件中的数据按照【指定编码】读取到Java程序中。

    InputStreamReader构造方法:

        InputStreamReader(InputStream in): 需要传递一个字节输入流。 会采用平台的默认编码进行读取。

        InputStreamReader(InputStream in, String charsetName): 第一个参数是字节输入流。 第二个参数表示编码方式。

    转换流其实本身也并不具备读或者写的功能,转换流做的事情其实是查询后码表转码的过程。

    使用步骤:

        1. 创建一个InputStreamReader对象

        2. 调用read方法读取

        3. 释放资源。

    注意:如果指定的编码方式不存在,那么就会抛出异常

public class Demo02InputStreamReader {

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

//        readGBK();

        readUTF8();

    }

 

    //使用转换流读取UTF-8格式的文件

    public static void readUTF8() throws IOException {

        //创建一个转换流对象

        //构造方法没有指定编码,那么采用的就是默认编码 utf-8

        //InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file02-utf8.txt"));

        //也可以单独指定一个UTF-8编码

        InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file02-utf8.txt"), "utf-8");

 

        //开始读取

        //一次读取一个字符

        int i;

        while((i = isr.read()) != -1) {

            //打印

            System.out.print((char)i);

        }

        //释放资源

        isr.close();

    }

 

    //使用转换流读取GBK编码的文件

    public static void readGBK() throws IOException {

        //创建一个InputStreamReader对象,指定要读取的编码方式

        InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file01-gbk.txt"), "gbk");

        //InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file01-gbk.txt"), "utf-8");

        //开始读取

        //一次读取一个字符

        int i;

        while((i = isr.read()) != -1) {

            //打印

            System.out.print((char)i);

        }

        //释放资源

        isr.close();

 

    }

}

 

2、OutputStreamWriter也是转换流, 用来写, 可以指定编码进行写入操作。

    OutputStreamWriter构造方法:

        OutputStreamWriter(OutputStream out): 参数传递字节输出流。 会采用平台默认编码方式进行写入

        OutputStreamWriter(OutputStream out, String charsetName): 参数传递字节输出流。 第二个参数charsetName为要写的编码方式.

    使用步骤:

        1. 创建OutputStreamWriter对象,指定要写入的编码方式

        2. 调用write方法,写数据

        3. 释放资源

public class Demo03OutputStreamWriter {

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

        //writeGBK();

        writeUTF8();

    }

 

    //以UTF-8方式写数据

    public static void writeUTF8() throws IOException {

        //创建一个OutputStreamWriter对象

        //不指定编码,采用的是idea默认编码utf-8

        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file04-utf8.txt"));

        //也可以指定编码,编码方式为utf-8

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file04-utf8.txt"), "utf-8");

        //调用write写

        osw.write("你好");

 

        //释放资源

        osw.close();

    }

 

    //定义方法,以GBK方式写入

    public static void writeGBK() throws IOException {

        //创建OutputStreamWriter对象,指定要写入的编码方式

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file03-gbk.txt"), "gbk");

        //调用write方法写数据。

        osw.write("你好");

 

        //释放资源

        osw.close();

    }

}

 

3、将GBK编码的文本文件,转换为UTF-8编码的文本文件。

    思路:

        1. 创建一个转换流,用来读取GBK编码的文件。

        2. 创建一个转换流,用来向UTF-8文件中写数据。

        3. 读取GBK编码的文件, 将读取出来的内容写入到UTF-8文件中即可.

        4. 释放资源

public class Demo04Test {

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

        //创建一个转换流,用来读取GBK编码的文件。

        InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file05-test.txt"), "gbk");

        //创建一个转换流,用来写UTF-8编码的文件

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file06-test.txt"), "utf-8");

        //开始读写,采用gbk的方式从gbk编码的文件中读取数据

        int i;

        while((i = isr.read()) != -1) {

            //i就是读取到的字符.

            //把这个字符以UTF-8的方式写到目的地文件

            osw.write(i);

        }

        //释放资源

        osw.close();;

        isr.close();

    }

}

三、序列化流

    1、ObjectOutputStream叫做序列化流,可以将Java程序中的对象写到文件中。

    序列化流本身也并不具备读或者写的功能,它的作用是把对象转成字节。

    ObjectOutputStream 构造方法:

        ObjectOutputStream(OutputStream out):参数需要传递一个字节输出流对象。

    写对象的方法:

        void writeObject(Object obj): 向文件中写入对象

    使用步骤:

        1. 创建序列化流对象。

        2. 调用方法,向文件中写一个对象

        3. 释放资源。

     注意:

    要序列化的对象, 它的类必须实现Serializable接口。 如果没有实现这个接口,那么会抛出异常

public class Demo01ObjectOutputStream {

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

        //创建序列化流对象。

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10\\file04-obj.txt"));

        //低啊用writeObject方法写一个Person对象

        Person p = new Person("大幂幂", 34);

        oos.writeObject(p);

 

        //释放资源

        oos.close();

    }

}

2、ObjectInputStream叫做反序列化流, 可以将文件中的对象读取到Java程序中

    ObjectInputStream构造方法:

        ObjectInputStream(InputStream in): 参数需要传递一个字节输入流。

    读取对象的方法:

        Object readObject(): 读取一个对象。

    使用步骤:

        1. 创建ObjectInputStream对象

        2. 调用readObject方法,读取文件中保存的对象

        3. 释放资源

    当调用readObject方法读取对象的时候,如果这个对象的类不存在了,那么就会抛出ClassNotFoundException

public class Demo02ObjectInputStream {

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

        //创建ObjectInputStream对象

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day10\\file04-obj.txt"));

        //调用readObject方法,读取文件中保存的对象

        Object obj = ois.readObject();

 

        Person p = (Person)obj;

        System.out.println(p.getName() + "-" + p.getAge());

 

        //释放资源

        ois.close();

 

    }

}

3、 注意:

        1. static修饰的成员不能被序列化。

        2. 如果希望某个成员变量不会被序列化,那么同时又不希望使用static关键字。 我们可以使用

           transient关键,这个关键字表示瞬态。 被transient修饰的成员变量不会被序列化。

public class Demo03StaticAndTransient {

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

        //writeObject();

        readObject();

    }

 

    //读对象

    public static void readObject() throws IOException, ClassNotFoundException {

        //创建反序列化流

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day10\\file05-obj.txt"));

        //调用readObject方法读取对象

        Object obj = ois.readObject();

        Person p = (Person)obj;

        System.out.println(p.getName() + "-" + p.getAge());

        //释放资源

        ois.close();

    }

 

    //写对象

    public static void writeObject() throws IOException {

        //创建序列化流

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10\\file05-obj.txt"));

        //调用方法,写对象

        oos.writeObject(new Person("柳岩", 20));

        //释放资源

        oos.close();

    }

}

public class Demo04ObjectStream {

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

        //writeObject();

        readObject();

    }

 

    //从文件中读取对象

    public static void readObject() throws IOException, ClassNotFoundException {

        //创建一个ObjectInputStream

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day10\\file06-obj.txt"));

        //调用readObject方法读取对象

        Object obj = ois.readObject();

        Person p = (Person)obj;

        System.out.println(p.getName() + "-" + p.getAge());

 

        //释放资源

        ois.close();

    }

 

    //向文件中写一个对象

    public static void writeObject() throws IOException {

        //创建一个ObjectOutputStream对象

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10\\file06-obj.txt"));

        //调用writeObject方法,向文件中写Person对象

        oos.writeObject(new Person("大幂幂", 30));

        //释放资源

        oos.close();

    }

}

4、练习: 将存放多个Person对象的集合写入到file07-test.txt文件中。

          在反序列化,读取文件中的集合对象,然后对集合中的内容进行遍历

    思路:

        1. 创建集合保存Person

        2. 向集合中添加Person对象

        3. 创建序列化流ObjectOutputStream对象

        4. 调用writeObject方法,将这个集合写到文件中。

        5. 关闭序列化流

        6. 创建反序列化流ObjectInputStream对象

        7. 调用readObject方法,读取对象

        8. 遍历读取到的集合

        9. 关闭反序列化流

public class Demo05Test {

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

        //创建集合保存Person

        ArrayList<Person> list = new ArrayList<>();

        //向集合中添加Person对象

        list.add(new Person("张无忌", 12));

        list.add(new Person("周芷若", 11));

        list.add(new Person("赵敏", 10));

 

        //创建序列化流ObjectOutputStream对象

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10\\file07-test.txt"));

        //调用writeObject方法,将这个集合写到文件中。

        oos.writeObject(list);

        //关闭序列化流

        oos.close();

 

        //创建反序列化流ObjectInputStream对象

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day10\\file07-test.txt"));

        //调用readObject方法,读取对象

        ArrayList<Person> list2 = (ArrayList<Person>)ois.readObject(); //把读取出来的对象强转成ARrayList然后赋值

        //遍历集合

        for (Person p : list2) {

            System.out.println(p.getName() + "-" + p.getAge());

        }

        //释放资源

        ois.close();

    }

}

5、 Serializable这个接口中没有任何的方法,这个接口的作用是做为一个标记。

    只有实现这个接口,这个类的对象才能够被序列化。

    如何给类固定分配一个版本号?

        提供一个成员变量即可,这个成员变量叫做serialVersionUID。 并且使用private static final修饰

        并且这个成员变量是long类型。

public class Person implements Serializable{

 

    //此时这个类的版本号永远是1,不管对这个类如何修改,这个类的版本号永远不会变永远是1.

    private static final long serialVersionUID = 1L;

 

    private String name;

    private /*static*/ /*transient*/ 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;

    }

}

四、打印流

 

1、打印流

        PrintStream: 字节打印流

        PrintWriter: 字符打印流

    打印流的特点:

        1. 输出内容相对来说比较简单。

        2. 这个流只有输出,没有输入。

    PrintStream 构造方法:

        PrintStream(File file): 参数传递File对象

        PrintStream(OutputStream out): 传递一个字节输出流

        PrintStream(String fileName): 传递一个字符串。

    写数据的方法:

        print: 输出但是不换行

        println:输出并直接换行

        write: 可以写字节数组,写字节数组的一部分,写字节

    print和write的区别: 如果参数传递数字write方法会查询ASCII码表写入对应的字符。print方法会原样输出。

public class Demo01PrintStream {

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

        //创建一个打印流对象

        PrintStream ps = new PrintStream("day10\\file08.txt");

        //调用print方法,向文件写数据

        //ps.print("你好");

        //ps.print("我好");

        //ps.println("你好");

        //ps.println("我好");

 

        //ps.write("你好".getBytes());

 

        //ps.println(100); //100

        ps.write(100);//d

        //释放资源

        ps.close();

    }

}

 

public class Demo02PrintStreamTest {

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

        //创建一个打印流

        PrintStream ps = new PrintStream("day10\\file09.txt");

        //使用System.setOut改变打印流的流向

        System.setOut(ps); //此时通过System.out.println打印的内容都会输出到file09.txt中

 

        System.out.println("你好");

    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值