栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java IO流中的处理流

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java IO流中的处理流

IO流中的处理流
  • 1,处理流之一:缓冲流的使用
    • 2.1,缓冲流实现非文本文件的复制
    • 2.2,缓冲流实现文本文件的复制
  • 2,处理流之二:转换流的使用
  • 3,其他处理流(非重点)
    • 3.1,标准输入、输出流(了解)
    • 3.2,打印流(了解)
    • 3.3,数据流(了解)
  • 4,处理流之三:对象流(重点)
    • 4.1,对象序列化机制的引入(要会描述)
    • 4.2,对字符串对象进行序列化和反序列化操作:
    • 4.3,自定义类的序列化和反序列化操作
    • 4.4,对象流总结,场景类比

1,处理流之一:缓冲流的使用

缓冲流(内部提供了一个缓冲区)能有效提高文件读写效率。

但要注意缓冲流不能直接作用于文件上,能够直接作用于文件上的是节点流(FileInputStream、OutputStream、Reader、Writer是节点流)。处理流是套接在节点流上进行处理的流。

缓冲流有:

  • 处理字节:BufferedInputStream、BufferedOutPutStream
  • 处理字符:BufferedReader、BufferedWriter

2.1,缓冲流实现非文本文件的复制

使用BufferedInputStream、BufferedOutPutStream

package com.atguigu.java;
import org.junit.Test;
import java.io.*;

public class BufferedTest {
    
    @Test
    public void BufferedStreamTest1(){
        BufferedInputStream bis= null; //处理流包住节点流
        BufferedOutputStream bos= null;
        try {
            //1,造File对象
            File srcFile=new File("img.png");
            File destFile=new File("img3.png");  //复制出一个img3.png
            //2,造节点流
            FileInputStream fis=new FileInputStream(srcFile);
            FileOutputStream fos=new FileOutputStream(destFile);
            //3,造处理流(此处是造缓冲流)
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //4,复制的细节:读,写
            byte[] buffer=new byte[10];   //byte对应字节流
            int len;
            while ((len=bis.read(buffer))!=-1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        //5,资源关闭(上面共四个流,关外层的流的时候会顺带关闭内层的流)
            if (bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


可以改写成方法,然后进行调用:

package com.atguigu.java;
import org.junit.Test;
import java.io.*;

public class BufferedTest {
    //实现文件复制方法
    public void copyFileWithBuffered(String srcPath,String destPath){
        BufferedInputStream bis= null; //处理流包住节点流
        BufferedOutputStream bos= null;
        try {
            //1,造File对象
            File srcFile=new File(srcPath);
            File destFile=new File(destPath);
            //2,造节点流
            FileInputStream fis=new FileInputStream(srcFile);
            FileOutputStream fos=new FileOutputStream(destFile);
            //3,造处理流(此处是造缓冲流)
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //4,复制的细节:读,写
            byte[] buffer=new byte[1024];   //byte对应字节流
            int len;
            while ((len=bis.read(buffer))!=-1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5,资源关闭(上面共四个流,关外层的流的时候会顺带关闭内层的流)
            if (bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Test
    public void testCopyWithBuffered(){
        long start = System.currentTimeMillis();
        String srcPath="F:\programming\1-视频.avi";
        String descPath="F:\programming\010-视频-副本.avi";
        copyFileWithBuffered(srcPath,descPath);
        long end = System.currentTimeMillis();
        System.out.println("复制操作花费的时间为:"+(end-start));
    }
}

复制成功:

此处的缓冲流花费时间为549ms,而上期使用节点流耗时2000ms。显然使用缓冲流比使用节点流复制速度要快很多。

2.2,缓冲流实现文本文件的复制

使用BufferedReader、BufferedWriter(不能处理非文本文件)

①首先在当前module day09下建立一个sanguo.txt的文件,里面随意插入一些文本内容

②编写程序

package com.atguigu.java;
import org.junit.Test;
import java.io.*;

public class BufferedTest {
    @Test      //使用BufferedReader和BufferedWriter实现文本文件的复制
    public void test(){
        BufferedReader br= null;
        BufferedWriter bw= null;
        try {
            //1,熟练之后可以使用匿名方式:造文件和造流合并为一步
            br = new BufferedReader(new FileReader(new File("sanguo.txt")));
            bw = new BufferedWriter(new FileWriter(new File("zhaoyun.txt")));
            //2,读写操作
            //方式一:
            //char[] cbuf=new char[1024];  //字符型用char
            //int len;
            //while((len=br.read(cbuf))!=-1){
            //    bw.write(cbuf,0,len);
            //}

            //方式二:使用String搭配readline()
            //readline():一次读一行。返回当前读到的一行的数据(string型),不包含换行符;如果到末尾则返回null
            String data;
            while ((data=br.readLine())!=null){
                bw.write(data+"n");  //手动换行
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        //3,关闭资源
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


抽象基类节点流缓冲流(处理流的一种)
InputStreamFileInputStreamBufferedInputStream
OutputStreamFileOutputStreamBufferedOutPutStream
ReaderFileReaderBufferedReader
WriterFileWriterBufferedWriter
2,处理流之二:转换流的使用



要明确的是:两个转换流是字符流。看后缀


测试转换流的使用:

package com.atguigu.java;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class TransformTest {
    @Test
    public void test1(){
        InputStreamReader isr= null;
        try {
            FileInputStream fis=new FileInputStream("sanguo.txt");
            isr = new InputStreamReader(fis,"UTF-8");
            //InputStreamReader()中第参数1是一个字节的输入流,参数2指明字符集(不写则使用系统默认字符集utf-8)
            char[] cbuf=new char[20];
            int len;
            while ((len=isr.read(cbuf))!=-1){
                String str=new String(cbuf,0,len);    //输出到控制台
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

综合使用InputStreamReader和OutputStreamWriter:

如给文件sanguo.txt字符集换为GBK:

package com.atguigu.java;
import org.junit.Test;
import java.io.*;
public class TransformTest {
    @Test
    public void test1() {
        InputStreamReader isr= null;
        OutputStreamWriter osw= null;
        try {
            File file1=new File("sanguo.txt");
            File file2=new File("sanguo_gbk.txt");

            FileInputStream fis=new FileInputStream(file1);
            FileOutputStream fos=new FileOutputStream(file2);

            isr = new InputStreamReader(fis,"utf-8");
            osw = new OutputStreamWriter(fos,"gbk");

            char[] cbuf=new char[20];
            int len;
            while ((len=isr.read(cbuf))!=-1){
                osw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (osw!=null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

成功生成编码为gbk的sanguo_gbk.txt文件:

3,其他处理流(非重点) 3.1,标准输入、输出流(了解)

3.2,打印流(了解)

3.3,数据流(了解)

4,处理流之三:对象流(重点)

4.1,对象序列化机制的引入(要会描述)


4.2,对字符串对象进行序列化和反序列化操作:
package com.atguigu.java;
import org.junit.Test;
import java.io.*;

public class ObjectInputOutputStreamTest {

    
    @Test
    public void test1(){         //运行test1后,可以在当前module下生成一个名为object.dat的文件
        ObjectOutputStream oos= null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            oos.writeObject(new String("我爱北京天安门"));  //把此字符串信息持久化起来
            oos.flush(); //刷新操作
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    @Test 
    public void test2(){  //运行test2后,控制台输出“我爱北京天安门”
        ObjectInputStream ois= null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            Object obj = ois.readObject(); //返回的实际是个字符串
            String str= (String)obj;
            System.out.println(str);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois!=null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

String 内部实现了serializable接口

4.3,自定义类的序列化和反序列化操作

注意:

要想使一个自定义类的Java对象可序列化需要满足相应的要求:
(否则不能序列化成功)

  • ①实现Serializable接口
  • ②当前类需要提供一个全局常量:serialVersionUID
  • ③除了当前Person类需要实现Serializable接口,还要保证当前类内部所有属性必须是可序列化的。(默认情况下基本数据类型是可序列化的,要注意自定义的属性)

上面的序列化一个String类型的对象没有报错,原因是String内部已经做了相关操作。而我们的自定义类则需要手动去完成这三个需求。

代码演示:
①自定义Person类:

package com.atguigu.java;
import java.io.Serializable;

public class Person implements Serializable {     //其实Serializable接口内部啥也没有,只起到标识作用,表明相应类的对象可序列化
    public static final long serialVersionUID=6523563535L;   //序列版本号,随便写一个值
    private String name;
    private int age;
    private Account acct;        //Account是自定义的,所以该属性也应该设置为可序列化的。否则不能序列化成功

    public Person(){

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

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

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", acct=" + acct +
                '}';
    }
}

class Account implements Serializable{   //Accountu而要满足可序列化的三个要求
    public static  final long serialVersionUID=6553637658L;
    private double balance;

    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }
    public void setBalance(double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }
}

②测试代码:

package com.atguigu.java;
import org.junit.Test;
import java.io.*;

public class ObjectInputOutputStreamTest {

    
    @Test
    public void test1(){         //运行test1后,可以在当前module下生成一个名为person.dat的文件。成功持久化对象
        ObjectOutputStream oos= null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("person.dat"));
            oos.writeObject(new Person("喜羊羊",23));  //把自定义类对象持久化起来
            oos.flush(); //刷新操作
            oos.writeObject(new Person("懒羊羊",23,new Account(5000)));
            oos.flush(); //刷新操作
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    @Test
    public void test2(){
        ObjectInputStream ois= null;
        try {
            ois = new ObjectInputStream(new FileInputStream("person.dat"));
            Object obj1 = ois.readObject();
            Person p1= (Person) obj1;

            Object obj2 = ois.readObject();
            Person p2= (Person) obj2;

            System.out.println(p1);  //默认调用相应的toString方法
            System.out.println(p2);  //默认调用相应的toString方法
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois!=null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4.4,对象流总结,场景类比

想象在2090年,小明想带一条,去世界某个地方旅游,不需要交通工具。只需要小明(对象)进入一个时空门,然后就变为一个二进制流(序列化)。目的地的一端使用时空门接受此二进制流,然后再转换为小明实体(反序列化);但不是所有东西都可以任意转化为二进制流,必须贴上一个Serialable(接口)的标签,指明有此转化功能。并且有一个唯一的序号serialVersionUID;人有人的serialVersionUID,有的serialVersionUID,不能乱套,否则人穿梭过去可能变成。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/837924.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号