JAVA零学习之基础归纳(十五)--字节流、字符流、异常处理、Properties

字节流、字符流、异常处理、Properties

一、IO流

1.1 IO
  • I:input:输入(读取) 把硬盘中的数据,读取到内存中使用,输入流
  • O:output:输出(写入) 把内存中的东西,写入到硬盘中,输出流
  • 流:数据(字符字节) 1个字符 = 2个字节 = 8个二进制位
1.2 IO的分类
  • 根据流向:输入流和输出流
    • 输入流:把数据从其他设备上读取到内存中的流
    • 输出流:把数据从内存中写出到其他设备上的流
  • 数据类型:字节流和字符流
    • 字节流:以字节为单位。
    • 字符流:以字符为单位
1.3 IO流的超类
输入流 输出流
字节流 字节输入流:InputStram 字节输出流:OutputStream
字符流 字节输出流:Read 字符输出流:Writer

二、字节流

2.1 一切皆为字节
  • 一切文本(文本、图片、视频)等在存储的时候都是以二进制的形式保存的,都是一个字节,所以字节流可以传输任意文件数据。
  • 底层传输都是二进制数据
2.2 字节输出流 【 OutputStream 】

java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定字节信息写出到目的地,它定义了字节输出流的基本共性功能方法

  • public void close():关闭此输出流并释放此流相关的任何系统资源
  • public void flush():刷新此输出流并强制任何缓冲的输出字节被写出
  • public void write(byte[]b):将b.length个字节从指定的字节数组写出到目的地
  • public void write(byte[]b,int off,int len):从指定的字节数组写出len字节,从偏移量off开始。
  • public abstract void write(int b):将指定的字节输出流

【close 方法,当完成流的操作时,必须调用此方法,释放系统资源】

2.3 数据写出到文件 FileOutputStram 类
2.3.1 构造方法
  • public FileOutputStream(File file):创建文件输出流以写入指定的File对象
  • public FileOutputStream(File file, boolean append) 创建文件输出流以写入指定的File对象,true表示采用追加模式,false采用覆盖模式
  • public FileOutputStream(String name):创建文件输出流以指定的名称写入文件。
  • 创建一个 FileOutputStream 对象
  • 会根据构造方法中的传递的文件/文件路径,创建一个空的文件
  • 会把 FileOutputStream 对象指向创建好的文件

【步骤:

​ 1、 准备一个字节输出流对象,并指定文件

​ 2、 调用write方法,写数据

​ 3、 调用flush方法,刷新

​ 4、 在finally代码块中,关闭IO流对象,以释放所占的内存资源

2.4 字节输入流 【InputStream】
  • java.io.InputStream 抽象类是表示输入流的所有类的超类,可以读取字节信息到内存中,它定义了字节输入流的基本共性的方法。
  • public void close():关闭此输入流对象释放资源
  • public abstract int read():从输入流中读取一个字节
  • public int read(byte[]b):从输入流中读取一些字节,并将它们存储到字节数组b中
2.5 FileInputStream 类

java.io.FileInputStream类是文件输入流,从文件中读取字节

构造方法

  • public FileInputStream(File file): 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
  • public FileInputStream(String name):通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
package com.bdit.test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test01 {
    public static void main(String[] args) {
        FileOutputStream fios = null;
        try {
            //创建字节输出流
              fios = new FileOutputStream(new File("F:\\bdit\\os\\osa.txt"));
//            fios = new FileOutputStream("F:\\bdit\\os\\osb.txt");//以字符串模式写入地址
//            fios = new FileOutputStream(new File("F:\\bdit\\os\\osa.txt"),true);   可以连续写入(默认是覆盖模式,写入rtue是追加)
            //写入   write只能int和char类型,并且会转成AScii
            fios.write(100);
            fios.write(new byte[]{101,102,103,104});
            fios.write("\r\n".getBytes());//换行
            fios.write(new byte[]{101,102,103,104,105},2,3);//从第三个开始(包括第三个)往后截取3个
            fios.write("\r\n".getBytes());
            String str01 = "山东省";
            byte[] ch01 =str01.getBytes();
            fios.write(ch01);
            fios.write('a');
            fios.write("甲二".getBytes());
            fios.write("jiaer".getBytes());
            //刷新
            fios.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭输入流
            try {
                fios.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
package com.bdit.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Test02 {
    public static void main(String[] args) {
        //字节输入流
        FileInputStream flos = null;
        try {
            //创建字节输入流
            flos=new FileInputStream(new File("F:\\bdit\\os\\osa.txt"));
            //读取数据
            int a = flos.read();
            while(a!=-1){
                System.out.print((char)a+" ");
                a=flos.read();
            }

/*            flos.read(new byte[]{101,102,103,104});
            flos.read(new byte[]{101,102,103,104},1,3);*/

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                flos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
2.6 练习

实现图片的复制

package com.bdit.vifition;

import java.io.*;

//通过字节输入输出流实现图片的复制
public class Vifi02 {
    public static void main(String[] args) {
        FileInputStream filios = null;
        FileOutputStream fos =null;

        try {
            filios = new FileInputStream(new File("F:\\bdit\\c\\guolvqi.png"));
            fos = new FileOutputStream(new File("F:\\bdit\\b\\aa.png"));
            int a = filios.read();
            while (a!=-1){
             //   System.out.println((char)a);
                //读写
                fos.write(a);
                a=filios.read();
            }

            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                if (filios!=null){
                    filios.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if (fos!=null){
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

【字节流只适合用于操作,图片、视频、音频等以字节为单位存储数据的文件,不适合操作文本文件】

三、字符流

当字节流读取的时候,遇到中文字符的时,可能不显示完整的字符,因为一个中文字符占用两个字符存储,所以java提供了字符流,以字符为单位读写数据,专门用于处理文本文件的。

3.1 字符输入流 【Reader】

java.io.Reader 抽象类是表示用于读取字符的所有类的超类,可以读取字符信息到内存中。

  • public void close():关闭对象释放所占的系统资源
  • public int read():读取一个字符
  • public int read(char[] buf):从输入流中读取一些字符,存储到字符数组中。
3.2 FileReader类

java.io.FileReader类是读取字符文件的类,构造方法使用系统默认的字符编码和默认字节缓冲区。

【1. 字符编码:字节与字符的对应规则,Windows系统的中文编码默认是GBK编码表,IDEA中UTF-8

【2. 字节缓冲区:一个字节数组,用来临时存储字节数据的】

构造方法

  • FileReader(File file):创建一个新的 FileReader ,给出 File读取。
  • FileReader(String fileName):创建一个新的 FileReader ,给定要读取的文件的名称。
package com.bdit;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/*
FileReader 字符输入流
 */
public class Demo5 {
    public static void main(String[] args)throws IOException {
        FileReader fr=new FileReader(new File("e:\\a.txt"));
        int len;
        char[]cbuf=new char[2];
        while((len=fr.read(cbuf))!=-1){
            //System.out.println((char)len);
            System.out.println(new String(cbuf));
        }
        fr.close();
    }
}

3.3 字符输出流 【Writer】

java.io.FileWriter 类是写出字符到文件的类,构造时使用系统默认的字符编码和默认字节缓冲区

  • void write(int c):写入单个字符
  • void write(char[]cbuf):写入字符数组
  • abstract void write(char[]cbuf,int off,int len):写入字符数组的某一部分,off数组的开始位置,len写的字符个数
  • void write(String str):写入字符串
  • void flush():刷新该流的缓冲
  • void close():关闭对象,释放资源
3.4 FileWriter 类

java.io.FileWriter类是写出字符到文件的类,构造时使用系统默认的字符编码和默认字节缓冲区

构造方法

  • FileWriter(File file) 给一个File对象构造一个FileWriter对象。
  • FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。
  • FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
  • FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
package com.bdit;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/*
FileWriter字符输出流
 */
public class Demo6 {
    public static void main(String[] args)throws IOException {
        FileWriter fw=new FileWriter(new File("e:\\a.txt"));
        fw.write("张高三李四");
        fw.write(48);
        fw.write(new char[]{'a','b','c'});
        
        fw.close();
    }
}

3.5 关闭和刷新

因为内置缓冲区的原因:不关闭输出流,就无法写出字符到文件里,但是关闭的流对象,是无法继续写出数据的,如果我们要同时写数据和使用流,就需要flush 方法了。

  • flush:刷新缓冲区,流对象可以继续使用
  • close:先刷新缓冲区,然后通知系统释放资源,流对象不可再使用
  • 使用完流一定要关闭

四、异常处理

4.1 jdk7之前
public class Demo1 {
    public static void main(String[] args) {
        FileOutputStream fos=null;
        try {
            //创建对象
            fos = new FileOutputStream(new File("E:\\a.txt"),true);
            fos.write(97);
            fos.write(98);
            fos.write(99);
            fos.write('w');
            fos.write(49);
            //一个汉字占两个字节,所以如果写中文就会乱码
            fos.write('博');
            //
            fos.write("zhangsan".getBytes());
            fos.write("博道IT实训".getBytes());

            byte[]b="abcde".getBytes();
            fos.write(b,2,2);

            //windows系统里,换行符是\r\n
            fos.write("\r\n".getBytes());
            fos.write("javase".getBytes());


        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                //关闭
                fos.close();
            }catch (IOException ce){
                ce.printStackTrace();
            }
        }
    }
}

4.2 jdk7的处理

jdk7支持 try-with-resource 语句,该语句确保了每个资源在语句结束时关闭,所谓的资源(resource)指在程序完成后,必须关闭的对象

try(需要关闭的资源对象,如果多个使用;隔开){ }catch(Exception ce){ }

package com.bdit;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
    try-with-resource
 */
public class Demo7 {
    public static void main(String[] args) {
        try(FileReader fr=new FileReader("e:\\a.txt");
            FileWriter fw=new FileWriter("e:\\b.txt")){
            int len;
            while((len=fr.read())!=-1){
                System.out.println((char)len);
            }
        }catch (IOException ce){
            ce.printStackTrace();
        }
    }
}

4.3 jdk9的改进

JDK9中try-with-resource的改进,对于引入对象的方式,支持的更加简洁,被引入的对象,同样可以启动关闭无需手动close.

package com.bdit;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
    try-with-resource
 */
public class Demo8 {
    public static void main(String[] args)throws IOException {
        FileReader fr=new FileReader("e:\\a.txt");
        FileWriter fw=new FileWriter("e:\\b.txt");
        try(fr;fw){
            int len;
            while((len=fr.read())!=-1){
                System.out.println((char)len);
            }
        }catch (IOException ce){
            ce.printStackTrace();
        }
    }
}


五、属性集 Properties

5.1 概述

【HashMap 和Hashtable 都是通过 key=value 来存储数据,他的区别在于,Hashtable不能把null当作key和value】

java.util.Properties 继承自 Hastable ,来表示一个持久的属性及集,它使用键值对的结构存储数据,每个键及其对应的值都是一个字符串。

5.2 创建属性文件
  • 属性文件一般放置在src根目录下,属性文件的后缀名.properties
  • 属性文件中,每一行只能写一个key=value,而且不需要任何的符合来修饰
5.3 构造方法
  • Properties() 创建一个没有默认的空属性列表

基本的存储方法

  • public Object setProperty(String key, String value):保存一对键值对
  • public String getProperty(String key):根据键获取值
package com.bdit;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/*
Properties属性集
 */
public class Demo9 {
    public static void main(String[] args) throws IOException {
        //读取config.properties属性文件
        InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties");
        //创建Properties对象
        Properties properties=new Properties();
        //把InputStream对象加载到properties对象中
        properties.load(inputStream);
        //根据key获取值

        String name=properties.getProperty("name");
        String age=properties.getProperty("age");
        String address=properties.getProperty("address");
        //给属性集对象中的key设置值
        properties.setProperty("id","1006");
        String id=properties.getProperty("id");
        System.out.println(id+" "+name+" "+age+" 
        "+address);
    }
}

六、序列化流

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

【为什么要序列化?序列化后的数据,都会以二进制的形式在网络中进行传输,通过反序列化可以在任何一个终端进行数据的还原,简单的来说就是为了数据能够更方便地在网络中进行传输】

6.2 ObjectOutputStream 类
  • java.io.ObjectOutputStream类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。

构造方法

  • ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
6.3 序列化操作
  • 一个对象想要序列化
    • 必须实现 java.io. Serializable接口 ,该接口是一个标记接口,凡是有该接口的类的对象都可以序列化,如果没有实现该接口,则该类无法序列化或者反序列化同时还会爆出 NotSerializableException 问题
    • 想要序列化,其类的属性一定是可序列化的,不能是被transient、static 关键字修饰
6.4 反序列化

ObjectInputStream 但序列化流

构造方法
  • ObjectInputStream(InputStream in): 创建从指定的InputStream读取的ObjectInputStream。
  • public final Object readObject():读取一个对象
package com.bdit.xulie;

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = 4759662288187860941L;
    private String id;
    private String name;
    private int age;

    public Student(){}

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

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    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 "Student{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.bdit.xulie;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.Scanner;
import java.util.zip.InflaterOutputStream;
//序列化
public class Xulie01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try(FileOutputStream fos =new FileOutputStream("F:\\bdit\\aas.txt");
            ObjectOutputStream obj = new ObjectOutputStream(fos)){
            Student stu01 = new Student("1001","张三",20);
 
            obj.writeObject(stu01);

            Student stu02 = new Student("1002","李四",25);
            obj.writeObject(stu02);
            Student stu03 = new Student("1002","李四",25);
            obj.writeObject(stu03);

        }catch (Exception ec){
            ec.printStackTrace();
        }


    }

}
package com.bdit.xulie;

import java.io.FileInputStream;
import java.io.ObjectInputStream;
//反序列化
public class Fanxuli {
    public static void main(String[] args) {

        try(FileInputStream fin = new FileInputStream("F:\\bdit\\aas.txt");
            ObjectInputStream oins = new ObjectInputStream(fin);){
            /*一个
            Object obj =oins.readObject();
            Student student = (Student)obj;
            System.out.println(student);*/

            while (oins!= null){
                Student student = (Student)oins.readObject();
                System.out.println(student);
//                oins.readObject();
            }
        }catch (Exception ec){
           // ec.printStackTrace();
        }
    }
}

当JVM反序列化对象时,抛出了一个InvalidClassException异常,发生这个异常的原因如下:

1、 该类的序列化版本号与从流中读取的类描述的版本不匹配

2、 该类包含未知数据类型

Serializable

接口给需要序列化的类,提供了一个序列化版本号,

该版本号的目的在于验证序列化的对象和对应类是否版本匹配

你可能感兴趣的:(java,jvm)