学习博客:IO流之字节流(InputStream、OutputStream)

字节输入流 InputStream,该抽象类是所有类字节输入流的超类
字节输出流 OutputStream,该抽象类是所有类字节输出流的超类

1.文件输入输出流

1.1 文件输入流 FileInputStream

import org.junit.jupiter.api.Test;

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

public class FileInputStream_ {
    public static void main(String[] args) {

    }

    //单个字节的读取,效率低
    @Test
    public void readFile01() {
        //路径
        String filePath = "D:\\test1.txt";
        int readData = 0;

        FileInputStream fileInputStream = null;

        try {
            //创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //从该输入流读取一个字节的数据,若没有输入,则阻止;返回-1则读取完毕
            while ((readData = fileInputStream.read()) != -1) {
                System.out.print((char) readData);     //强转为char
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileInputStream.close();    //关闭文件流
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

        //read(byte[] b),提高效率
        @Test
        public void readFile02() {
            //路径
            String filePath = "D:\\test1.txt";
            int readLen = 0;

            //字节数组
            byte[] buf = new byte[8];   //一次读取8个字节

            FileInputStream fileInputStream = null;

            try {
                //创建FileInputStream对象,用于读取文件
                fileInputStream = new FileInputStream(filePath);
                //从该输入流读取最多b.length字节的数据到字节数组b。此方法阻塞,知道
                //返回-1则读取完毕
                //读取正常,返回实际读取的字节数
                while ((readLen = fileInputStream.read(buf)) != -1) {
                    System.out.print(new String(buf, 0, readLen));     //显示字符
                }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    fileInputStream.close();    //关闭文件流
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

1.2 文件输出流 FileOutputStream

import org.junit.jupiter.api.Test;

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

public class FileOutputStream_ {
    public static void main(String[] args) {

    }

    @Test
    public void writeFile(){

        //创建FileOutputStream对象
        String filePath = "D:\\yy.txt";
        FileOutputStream fileOutputStream = null;

        try {
            //fileOutputStream = new FileOutputStream(filePath);  //覆盖
            fileOutputStream = new FileOutputStream(filePath,true); //追加
            //写入一个字节
            //fileOutputStream.write('y');
            //写入字符串
            //fileOutputStream.write("hi,java".getBytes());   // .getBytes() 字符串->字节数组
            //指定索引写入
            fileOutputStream.write("hi,java".getBytes(),0,2);   // .getBytes() 字符串->字节数组


        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

1.3 文件输入输出流的应用

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

//文件拷贝
public class FileCopy {
    public static void main(String[] args) {
        //源路径
        String srcFilePath = "D:\\1.png";
        //目标路径
        String destFilePath = "D:\\test\\1.png";
        //创建文件的输入流,将文件读取到程序
        FileInputStream fileInputStream = null;
        //创建文件的输出流,将读取到的文件数据写入指定路径
        FileOutputStream fileOutputStream = null;


        try {
            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream = new FileOutputStream(destFilePath);
            //定义一个字节数组,提高读取效率
            byte[] buf = new byte[1024];
            int readLen = 0;
            while((readLen = fileInputStream.read(buf)) != -1){
                //读取就写入,边读边写
                fileOutputStream.write(buf, 0, readLen);
            }
            System.out.println("拷贝成功");
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fileInputStream != null){
                    fileInputStream.close();    //关闭输入流
                    }
                if(fileOutputStream != null){
                    fileOutputStream.close();   //关闭输出流
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.缓冲字节输入输出流

缓冲字节输入流 BufferedInputStream,在创建BufferedInputStream时,会创建一个内部缓冲区数组

缓冲字节输出流 BufferedOutputStream,实现缓冲的输出流,可以将多个字节写入底层输出流中,不必对每次字节写入调用底层系统

字节流可以操作二进制文件,字符流不能操作二进制文件

应用

import java.io.*;

//二进制文件拷贝
public class BufferedCopy__ {
    public static void main(String[] args) {
        //路径
        String srcFilePath = "D:\\IMG_7489.JPG";
        String destFilePath = "D:\\1\\h.JPG";

        //创建BufferedInputStream对象和BufferedOutputStream对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));

            //循环读取文件,写入destFilePath
            byte[] buff = new byte[1024];
            int readLen = 0;
            while((readLen = bis.read(buff)) != -1){
                bos.write(buff, 0, readLen);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(bis != null){
                    bis.close();
                }
                if(bos != null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("拷贝成功");
    }
}

3.序列化(ObjectOutputStream)与反序列化(ObjectInputStream)

1.仅将程序(内存)中的数据写入至文件(磁盘),保存的是值
2.将程序(内存)中的保存值和数据类型写入至文件(磁盘),称作序列化
3.将保存在文件的数据(值和数据类型)恢复至程序,称作反序列化
4.若某个对象支持序列化机制,其类必须是可序列化的,需要是实现两个接口之一(Serializable(标记接口,没有方法)、Externalizable(需要是实现方法))

3.1 对象字节输出流 ObjectOutputStream(序列化)

创建一个Person类

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;
    
    //序列化对象时,默认将其所有属性都序列化,除static和transient修饰的成员
    private transient String nation;
    private static String city;
    
    //序列化对象时,其属性的类型也需要实现序列化接口
    private Hobby hobby = new Hobby();
    
    //serialVersionUID序列化版本号,可提高兼容性
    private static final long serialVersionUID = 1L;

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

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

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public static String getCity() {
        return city;
    }

    public static void setCity(String city) {
        Person.city = city;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nation='" + nation + '\'' +
                '}' + city + hobby;
    }
}

实现序列化

import com.yl.IO.Person;

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

public class ObjectOutputStream_ {
    public static void main(String[] args) throws Exception {

        String filePath = "D:\\data.dat";

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据
        oos.writeInt(10);  //int -> Integer (实现了Serializable)
        oos.writeBoolean(true); //boolean -> Boolean (实现了Serializable)
        oos.writeChar('q'); //char -> Charactor (实现了Serializable)
        oos.writeDouble(3.14159);   //double -> Double (实现了Serializable)
        oos.writeUTF("杨杨杨");    //String

        //保存一个Person对象
        oos.writeObject(new Person("架构师", 28, "china", "beijing"));

        oos.close();    //关闭流

        System.out.println("序列化成功");
    }
}

在这里插入图片描述

3.2 对象字节输入流 ObjectInputStream(反序列化)

import com.yl.IO.Person;

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

public class ObjectInputStream_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String filePath = "D:\\data.dat";

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));

        //读取(反序列化)的顺序需要和保存数据(序列化)的顺序一致

        System.out.println(ois.readInt());
        System.out.println(ois.readBoolean());
        System.out.println(ois.readChar());
        System.out.println(ois.readDouble());
        System.out.println(ois.readUTF());

        Object person = ois.readObject();
        System.out.println("运行类型:" + person.getClass());
        System.out.println("对象信息:" + person);   //底层 Object -> Person

        //若调用Person类中的方法,则需要向下转型,Person类必须在可以引用到的位置
        Person person2 = (Person)person;
        System.out.println(person2.getName());

        ois.close();    //关闭流
    }
}

在这里插入图片描述

小结
1.读写顺序一致
2.要求实现序列化\反序列化对象,需要实现Serializablea
3.序列化的类中添加序列化版本号 private static final long serialVersionUID = 1L 可以提高版本兼容性
4.序列化对象时,默认将其所有属性都序列化,除static和transient修饰的成员
5.序列化对象时,要求其属性的类型也要是实现序列化接口
6.序列化具备可继承性,若某类已实现序列化,则其所有子类也默认实现了序列化

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值