Day23知识总结

面试题

IO流对象分为那些

按功能分:输入流与输出流
按类型分:字节流与字符流

字节流:字节流按8bit传输,即以字节为单位输入输出
字符流:以字符为单位输入输出

按内存地址分:节点流与过滤流

节点流:从特定的地方读写流,例如磁盘或一块内存区域
过滤流:使用节点流作为输入或输出

常用流介绍

字节输入流:InputStream 抽象类

FileInputStream 文件字节输入流

BufferedInputStream 缓冲字节输入流

DataInputStream 数据字节输入流

ObjectInputStream 对象字节输入流[序列化流]

ByteArrayInputStream 字节数组输入流

字节输出流: OutputStream 抽象类

FileOutputStream 文件字节输出流

BufferedOutputStream 缓冲字节输出流

DataOutputStream 数据字节输出流

ObjectOutputStream 对象字节输出流[反序列化流]

ByteArrayOutputStream 字节数组输出流
PrintStream 打印输出流[打印至控制台]

字符输入流: Reader 抽象类

InputStreamReader 字节输入流转换为字符输入流

BufferedReader 字符缓冲输入流

FileReader 文件字符输入流

字符输出流: Writer 抽象类

OutputStreamWriter 字符输出流转换为字节输出流

BufferedWirter 字符缓冲输出流

FileWriter 文件字符输出流

FileInputStream & FileOutputStream(节点流)

节点流: 从特定的地方读写的流,例如磁盘或一块内存区域

FileInputStream : 输入流,操作的是字节,又叫字节流

FileOutputStrean: 输出流, 操作的是字节,又叫字节流

按字节读,读取效率低

作为编码时,字节没有符号位,8位都是数据位,其范围在0-255
byte数据类型范围 -128-127
因此在把数据读出强转为byte类型时,会存在溢出

一个中文占三个字节,采用utf-8编码

FileInputStream 读

对象.read() 读取一个字节int类
对象.read(byte数组) 读取数组长度的字节,返回读取到的字节长度

public class Demo1FileInputStream {
    public static void main(String[] args) {
        //文件的读写,离不开File对象
        File file=new File("C:\\Users\\LY\\Desktop\\heoll.txt");
        FileInputStream in=null;
        try {
            in=new FileInputStream(file);//输入流 按字节读、单位是byte
            int i = in.read();
            System.out.println("read: "+i);//读出的是字符
            // 可能出现的错误 要么抛出、要么捕获
            byte[] bs=new byte[3];
            in.read(bs);
            System.out.println(Arrays.toString(bs));
            //[50, 51, 52]
            byte[] bs1=new byte[30];
            in.read(bs1,5,20);
            System.out.println(Arrays.toString(bs1));
//[0, 0, 0, 0, 0, 53, 13, 10, -27, -113, -111, -25, -108, -97, -24, -65, -121, 13, 10, 103, 100, 99, 97, 115, 0, 0, 0, 0, 0, 0]
            //判断文件是否到末尾
            int i1 = in.read();//读取内容为-1.就表示读取到末尾
            System.out.println(i1);//-1
            //字节数组转字符串
            System.out.println(new String(bs));//234
            System.out.println(new String(bs1));//空格与换行
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();//关闭流
                //可能出现的错误 要么抛出、要么捕获
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

FileOutputStrean 写

对象.write()
对象.write(byte数组)

public static void main(String[] args) throws IOException {
        //创建对象
        //从文件开始位置开始写入
        FileOutputStream fos=new FileOutputStream("C:\\Users\\LY\\Desktop\\heoll.txt");
        //从文件末尾位置开始写入
        FileOutputStream fos1=new FileOutputStream("C:\\Users\\LY\\Desktop\\a.txt",true);
        //指定写入的文件不存在,输出流会先创建文件

        //写内容
        //按字节写 一个字节
        fos1.write(65);//字母A
        fos1.write(66);//字母B
        fos1.write(67);//字母C
        //批量写
        byte[] bs="疑是地上霜".getBytes(StandardCharsets.UTF_8);
        fos1.write(bs);
        byte[] bs1="举头望明月".getBytes(StandardCharsets.UTF_8);
        fos1.write(bs1,0,6);//一个中文三个字节
        fos1.close();
        fos.close();
    }

文件复制

public class Demo4FileCopy {
    public static void main(String[] args) throws IOException {
        //copy("C:\\Users\\LY\\Desktop\\a.txt","C:\\Users\\LY\\Desktop\\b.txt");
        //copy1("C:\\Users\\LY\\Desktop\\资料整理\\雄狮少年.pptx","C:\\Users\\LY\\Desktop\\资料整理\\XXXX.pptx");
        copy1("C:\\Users\\LY\\Desktop\\a","C:\\Users\\LY\\Desktop\\b");

    }

    public static void copy(String a,String b) throws IOException {
        FileInputStream in=new FileInputStream(a);
        FileOutputStream out=new FileOutputStream(b,true);
        int k;
        while ((k=in.read())!=-1){
            System.out.print(k+" ");
            out.write(k);
        }
        in.close();
        out.close();
    }
    public static void copy1(String a,String b) throws IOException {
        FileInputStream in=new FileInputStream(a);
        FileOutputStream out=new FileOutputStream(b,true);
        byte[] n=new byte[1000];
        int k=0;
        while (true){
            k=in.read(n);
            if(k<n.length)
                break;
            else {
                out.write(n);
            }
        }
        byte[] n1=new byte[k];

        out.write(n1);
        in.close();
        out.close();
    }
}

BufferedInputStream&BufferedOutputStream (过滤流)

使用节点流作为输入或输出
过滤流是使用一个已经存在的输入流或输出流进行创建的

BufferedInputStream

//BufferedInputStream:按字节读取,带缓冲区的输入流,读取效率高于FileInputStream
//创建对象的时候,需先创建字节流FileInputStream

public class Demo5BufferedInputStream {
    public static void main(String[] args) {
        FileInputStream fis=null;
        BufferedInputStream bis=null;
        try {
            fis=new FileInputStream("C:\\Users\\LY\\Desktop\\资料整理\\雄狮少年.pptx");
            //对象创建:通过字节流创建出带缓冲的输入流
            bis=new BufferedInputStream(fis);
            int read=bis.read();
            byte[] bs=new byte[1024];//1024字节,就是1k
            int read1=bis.read();
            if(read1==-1){
                System.out.println("末尾");
            }


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();//先关小的
                bis.close();//再关大的
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

BufferedOutputStream

//BufferedOutputStream:按字节读取,带缓冲区的输入流,读取效率高于FileOutputStream
//创建对象的时候,需先创建字节流FileOutputStream
//写入到缓冲区,到一定容量则自动写入文件
public class Demo6BufferedOutputStream {
    public static void main(String[] args) throws IOException {
        //创建对象
        FileOutputStream f=new FileOutputStream("C:\\Users\\LY\\Desktop\\aa.txt",true);//追加
        BufferedOutputStream bos=new BufferedOutputStream(f);
        //写入数据
        String str="fwfgeg dwfwff dwfwfs ferff";
        bos.write(65);//写入到缓冲区
        bos.write(str.getBytes(StandardCharsets.UTF_8));
        bos.flush();//手动刷新,把缓存区的数据,写入到文件中
        bos.close();//关闭流时,会先把缓冲区的数据写入文件即自动调用刷新机制,再关闭流
        f.close();

    }
}

DatainputStream & DataoutputStream

DataOutputStream & DataInputStream是对流功能的扩展,可以更方便读取int ,long ,char等类型的数据

DataOutputStream,对基本的输出流功能进行扩展,提供了基本数据类型的输出方法

DataInputStream,对基本的输入流功能的扩展,它提供了基本类型的输入方法

写入文件之后,如果用软件打开,会被继续为字符串

//DataOutputStream 按数据进行读
//DataInputStream 按数据进行读
public class Demo7DataOutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream out=new FileOutputStream("C:\\Users\\LY\\Desktop\\aa.");
        DataOutputStream dos=new DataOutputStream(out);
        dos.writeInt(100);
        dos.writeDouble(10.8);
        dos.writeChar('A');
        dos.writeUTF("中国你好");
        dos.close();
        //DataOutputStream写的顺序对应 与DataInputStream读取的顺序保持一致
        //java.io.EOFException 读的顺序与写的顺序不一致,可能会抛异常
        //数据流中写入数据时的顺序和读取时的顺序不一致
        FileInputStream in=new FileInputStream("C:\\Users\\LY\\Desktop\\aa.");
        DataInputStream ins=new DataInputStream(in);
        System.out.println(ins.readInt());
        System.out.println(ins.readDouble());
        System.out.println(ins.readChar());
        System.out.println(ins.readUTF());
        ins.close();
    }
}

InputStreamReader & OutputStreamWriter

提供字符的处理,一次处理一个字符(unicode)
字符的底层仍然是基本的字节流

InputStreamReader : 完成byte流解析为char流,按照编码解析

OutputStreamWriter:提供char流到字节,按照编码处理

//写字符/字符串,取char\char[]
//字符处理流
public class Demo8OutputStreamWriter {
    public static void main(String[] args) throws IOException {
        //创建对象
        FileOutputStream out= new FileOutputStream("C:\\Users\\LY\\Desktop\\bb.txt");
        OutputStreamWriter osw=new OutputStreamWriter(out);
        osw.write("清明时间雨纷纷,\n");
        osw.write("路上行人欲断魂。\n");
        osw.write("作者:XXX");
        osw.write('A');
        osw.write("这是一个首好诗".toCharArray());//写入缓存区
//        osw.flush();
        osw.close();//关之前先刷新,再关

        FileInputStream in=new FileInputStream("C:\\Users\\LY\\Desktop\\bb.txt");
        InputStreamReader irs=new InputStreamReader(in);
        char[] cd=new char[1000];
        int read=irs.read(cd);
        //去除多余的空格
        char[] cd1=new char[read];
        System.arraycopy(cd,0,cd1,0,read);
        //将char[]转换为String类型 String.valueOf();
        System.out.println(String.valueOf(cd1));
        //trim()去掉前后多余的空格
        System.out.println(String.valueOf(cd).trim());
        //表示已到文件末尾
        System.out.println(irs.read());//-1 表示已到文件末尾
        irs.close();
    }
}

BufferedReader & BufferedWriter

BufferReader & BufferWriter,更方便处理字符

//BufferedWriter
//BufferedReader
//带缓冲冲区的字符处理流,提供一行一行读取
//java.io.FileNotFoundException
//FileInputStream 给路径为绝对路径
public class Demo9BufferedWriter {
    public static void main(String[] args) throws IOException {
        //盘符不分大小写
//        FileInputStream in=new FileInputStream("E:\\IDEA_DATA\\javadata1\\javadata_one\\javase\\src\\day6\\Demo4FileCopy.java"); 
//        InputStreamReader isr=new InputStreamReader(in);
//        BufferedReader br = new BufferedReader(isr);
//
//        //br.readLine() 返回值为null 表示读到文件末尾
//        //br.readLine() 读取的是一行的内容
//        String s;
//        while ((s=br.readLine())!=null){
//            System.out.println(s);
//        }
//        br.close();
//        isr.close();
//        in.close();
        copy("E:\\IDEA_DATA\\javadata1\\javadata_one\\javase\\src\\day6\\Demo4FileCopy.java","C:\\Users\\LY\\Desktop\\cc.txt");
    }
    public static void copy(String s1,String s2) throws IOException {
        FileInputStream in=new FileInputStream(s1); //相对路径
        InputStreamReader isr=new InputStreamReader(in);
        BufferedReader br = new BufferedReader(isr);

        FileOutputStream out=new FileOutputStream(s2);
        OutputStreamWriter otr=new OutputStreamWriter(out);
        BufferedWriter wr=new BufferedWriter(otr);
        String s;
        while ((s=br.readLine())!=null){
             wr.write(s);
             wr.newLine();//需要手动换行
        }
        wr.close();
        br.close();
    }
}

对象序列化[ObjectInputStream&ObjectOutputStream]

将Object转换为byte序列,就是序列化,反之将byte序列转换为Object就是反序列化
对象序列化的目的,是为了将对象,以byte流的方式存储

使用writeObject(Object)/readObject()进行序列化和反序列化

ObjectInputStream ois ;
ois.readObject();

ObjectOutputStream oos ;
oos.writeObject(obj);

//ObjectInputStream 从文件中读取出对象
//ObjectOutputStream 把对象写入文件中
public class Demo10ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //写入对象
        File f=new File("E:\\IDEA_DATA\\javadata1\\javadata_one\\javase\\src\\day6\\Dobj.temp");
        /*
        FileOutputStream fos=new FileOutputStream(f);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        String str="hello";
        Integer i1=100;
        Date d=new Date();
        oos.writeUTF(str);
        oos.writeInt(i1);
        oos.writeObject(d);
        oos.flush();
        oos.close();
        */
        //读对象
        FileInputStream fis=new FileInputStream(f);
        ObjectInputStream ois=new ObjectInputStream(fis);
        //读注意顺序
        //java.lang.OptionalDataException
        System.out.println(ois.readUTF());
        System.out.println(ois.readInt());
        Object o=ois.readObject();
        System.out.println(o);//取出的是一个object变量
        //System.out.println(o.getTime()); 无法调用Date中的方法
        if(o instanceof Date){
            Date d=(Date) o;
            System.out.println(d.getTime());
        }
    }
}

Serializable接口

Serializable是序列化接口,对象必须实现序列化接口,才能进行序列化,否则抛出异常
java的API中的类,大部分都实现了Serializable接口

//对象序列化,再反序列化
//java.io.NotSerializableException 不可序列化
public class Demo11ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
       //序列化
        //java.io.InvalidClassException
         File f=new File("E:\\IDEA_DATA\\javadata1\\javadata_one\\javase\\src\\day6\\stu.temp");
        /*FileOutputStream out=new FileOutputStream(f);
        ObjectOutputStream oos=new ObjectOutputStream(out);
        Student student=new Student(10,100,"小红","1001");
        oos.writeObject(student);
        oos.flush();
        oos.close();*/
        //反序列化
        FileInputStream in=new FileInputStream(f);
        ObjectInputStream ios=new ObjectInputStream(in);
        Object b=ios.readObject();
        if(b instanceof Student){
            Student s=(Student) b;
            System.out.println(s.toString());
        }
        ios.close();

    }
}
//java.io.NotSerializableException 不可序列化
//要求需要将对象序列化至文件中,则需要将类实现序列化接口即implements java.io.Serializable
//实现可序列化接口 java.io.Serializable
class Student implements java.io.Serializable{
    int age;
    double money;
    String name;
    String id;

    public Student(int age, double money, String name, String id) {
        this.age = age;
        this.money = money;
        this.name = name;
        this.id = id;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", money=" + money +
                ", name='" + name + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}

面试题

对象序列化是什么, 用在什么声明场景

java的对象序列化,是为了保存各种对象在内存中的状态,并且保存的对象可通过反序列化再读出来,但被序列化的对象要求必须实现java.io.Serializable接口

例如,通过操作对象的流(ObjectInputStream与ObjectOutputStream),可以从文件中把数据读出来,或者将对象写入文件中

使用场景:
把内存中对象的状态保存到文件中或者数据库中;
网络上(Socket)传输对象的时候
想通过RMI(远程方法调用)传输对象的时候

transient关键字

transien,是java中的关键字,被其修饰的成员变量不会被序列化

private transient Integer brId;

import java.io.*;
//对象序列化,再反序列化
//java.io.NotSerializableException 不可序列化
//transient 透明的,一个关键字,被transient修饰成员变量。在对象被序列化时,不会把该变量的数据值保存在文件中
public class Demo11ObjectInputStream2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
       //序列化
        //java.io.InvalidClassException
        File f=new File("E:\\IDEA_DATA\\javadata1\\javadata_one\\javase\\src\\day6\\stu2.temp");
        /*FileOutputStream out=new FileOutputStream(f);
        ObjectOutputStream oos=new ObjectOutputStream(out);
        Student2 student=new Student2(10,100,"小红","1001");
        oos.writeObject(student);
        oos.flush();
        oos.close();*/
        //反序列化
        FileInputStream in=new FileInputStream(f);
        ObjectInputStream ios=new ObjectInputStream(in);
        Object b=ios.readObject();
        if(b instanceof Student2){
            Student2 s=(Student2) b;
            System.out.println(s.toString());
            //Student{age=10, money=100.0, name='null', id='null'}
        }
        ios.close();

    }

}
//java.io.NotSerializableException 不可序列化
//要求需要将对象序列化至文件中,则需要将类实现序列化接口即implements java.io.Serializable
//实现可序列化接口 java.io.Serializable
class Student2 implements Serializable{
    int age;
    double money;
    transient String name;
    transient String id;
    //transient 透明的,一个关键字,被transient修饰成员变量。在对象被序列化时,不会把该变量的数据值保存在文件中
    public Student2(int age, double money, String name, String id) {
        this.age = age;
        this.money = money;
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", money=" + money +
                ", name='" + name + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值