大数据笔记12—java基础篇8(异常、I/O )


苟有恒,何必三更眠五更起; 最无益,莫过一日曝十日寒。

异常

Throwable

分为两类:Error异常、exception异常

1.Error异常

​ 系统错误不用我们管

2.exception异常

​ 这个才是我们需要解决的异常

exception异常有两种

**RuntimeException:**编译器不报错,代码运行才知道 例如:角标越界、空指针、类型转换、、、

其他异常(编译时期的错误)

编译时期的错误在编译时期就会报错的一种异常
不代表我们写的代码有错误的只是在提醒我们有可能会发生错误

JVM的默认处理异常的方式

如果出现了问题, 我们自己没有处理, JVM会采用自动的处理方法, 它会把异常的类型, 原因, 位置直接打印到控制台上, 后边的代码是不能执行的

在这里插入图片描述

如何处理异常

利用try.catch.finally解决异常

格式:

try{

}catch(Exception e){
       e.printStackTrace()
}finally{
    //一般在这个地方释放资源
    //正常情况下都执行
}

特点: 处理完后, 程序会继续向下执行.

声明抛出异常
格式

  throws 异常的类型;		*//该内容是写到方法的形参列表之前的.* 

特点: 处理完后, 程序会终止执行

final, finally, finalize三个关键字之间的区别是什么?

答案:

finalize不是关键字他是方法.

final表示最终的。修饰符号,用来修饰:变量、方法、类

finally表示一直会执行。 是书写在try块后面。不论是否有异常发生,都会被执行

finalize表示释放资源。GC垃圾回收

finally里边的代码真的永远会执行吗?

答案:一般情况下都在执行,当在程序中使用了System.exit(0)//终止JVM虚拟机

File类

1、概述和构造方法

File类介绍

– 它是文件和目录路径名的抽象表示

– 文件和目录是可以通过File封装成对象的

– 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容 转换为具体存在的

• File类的构造方法

方法名说明
File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File(String parent, String child)从父路径名字符串和子路径名字符串创建新的 File实例
File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例
public static void main(String[] args) throws IOException {
        //File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
        File f1= new File("e:\\itcast\\java.txt");
        System.out.println(f1);
        //File(String parent, String child)	 从父路径名字符串和子路径名字符串创建新的 File实例
        File f2 = new File("e:\\itcast", "java.txt");
        System.out.println(f2);
        //File(File parent, String child)	 从父抽象路径名和子路径名字符串创建新的 File实例
        File f3 = new File("e:\\itcast");
        File f4 = new File(f3, "java.txt");
        System.out.println(f4);
    }

2、File类创建功能

• 方法分类

方法名说明
public boolean reateNewFile()当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
public boolean mkdir()创建由此抽象路径名命名的目录
public boolean mkdirs()创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
 //需求1:我要在E:\\itcast目录下创建一个文件java.txt
        File file = new File("E:\\itcast\\java.txt");
        System.out.println(file.createNewFile());
        System.out.println("--------------------");

        //需求2:我要在E:\\itcast目录下创建一个目录JavaSE
        File file1 = new File("E:\\itcast\\JavaSE");
        System.out.println(file.mkdir());
        System.out.println("--------------------");
        //需求3:我要在E:\\itcast目录下创建一个多级目录JavaWEB\\HTML
        File file2 = new File("E:\\itcast\\JavaWEB\\HTML");
        System.out.println(file2.mkdirs());
        //需求4:我要在E:\\itcast目录下创建一个文件javase.txt
        File file3 = new File("E:\\itcast");
        System.out.println(file3.createNewFile());

3、File类判断和获取功能

• 判断功能

方法名说明
public boolean isDirectory()测试此抽象路径名表示的File是否为目录
public boolean isFile()测试此抽象路径名表示的File是否为文件
public boolean exists()测试此抽象路径名表示的File是否存在

• 获取功能

方法名说明
public String getAbsolutePath()返回此抽象路径名的绝对路径名字符串
public String getPath()将此抽象路径名转换为路径名字符串
public String getName()返回由此抽象路径名表示的文件或目录的名称
public String[] list()返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles()返回此抽象路径名表示的目录中的文件和目录的File对象数组

• 方法分类

方法名说明
public boolean delete()删除由此抽象路径名表示的文件或目录
public static void main(String[] args) throws IOException {
    File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
    //File f= new File("e:\\itcast\\java.txt");
    //System.out.println(f1);
    File(String parent, String child)   从父路径名字符串和子路径名字符串创建新的 File实例
    //File f2 = new File("e:\\itcast", "java.txt");
    //System.out.println(f2);
    File(File parent, String child)     从父抽象路径名和子路径名字符串创建新的 File实例
    //File f3 = new File("e:\\itcast");
    //File f4 = new File(f3, "java.txt");
    //System.out.println(f4);
    //需求1:我要在E:\\itcast目录下创建一个文件java.txt
    //File file = new File("E:\\itcast\\java.txt");
    //System.out.println(file.createNewFile());
    //System.out.println("--------------------");
    需求2:我要在E:\\itcast目录下创建一个目录JavaSE
    //File file1 = new File("E:\\itcast\\JavaSE");
    //System.out.println(file.mkdir());
    //System.out.println("--------------------");
    需求3:我要在E:\\itcast目录下创建一个多级目录JavaWEB\\HTML
    //File file2 = new File("E:\\itcast\\JavaWEB\\HTML");
    //System.out.println(file2.mkdirs());
    需求4:我要在E:\\itcast目录下创建一个文件javase.txt
    //File file3 = new File("E:\\itcast");
    //System.out.println(file3.createNewFile());
    File f = new File("java.txt");
    System.out.println(f.isDirectory());
    System.out.println(f.isFile());
    System.out.println(f.exists());
    System.out.println("----------------");
    System.out.println(f.getAbsolutePath());
    System.out.println(f.getPath());
    System.out.println(f.getName());
    System.out.println("-------list---------");
    File file = new File("e:\\itcast");
    String[] list = file.list();
    for (String s : list) {
        System.out.println(s);
    }
    System.out.println("-------listFiles----------");
    File f2 = new File("E:\\itcast");
    File[] fileArray = f2.listFiles();
    for (File file1 : fileArray) {

            System.out.println(file1.getName());
    }
	//删除f文件
    System.out.println(f.delete());
    }

IO流简介

概述

IO流就是用来处理设备间的数据传输问题的

解释: i指的是Input(输入), o指的是Output(输出)

应用场景

• 文件复制

• 文件上传

• 文件下载

分类

• 按照流向分

输入流: 读取数据

输出流: 写入数据.

我们相当于程序,他输入输出的都是进入到程序里面的

所以输入程序=我们读取到输入到程序中的代码,输出就是程序去写入数据

按照操作分流

字节流: 以字节为单位来操作数据.

字符流: 以字符为单位来操作数据.

小技巧:

1 字节流能操作所有的文件类型

图片 视频 音频 文本文件

2字符流只能操作纯文本文件

3.简单理解:如果某个文件能用操作系统自带的记事本打开, 并且里边的内容你也能读得懂,

就可以考虑使用字符流, 否则, **使用字节流.

我们学习四中流

1.字节输入流: 以**字节为单位,来读取数据.**顶层抽象类是:InputStream.

2.字节输出流:以字节为单位,来写入数据.顶层抽象类是:OutputStream.

3.字符输入流:以字符为单位.来读取数据.顶层抽象类是:Reader.

4.字符输出流:以字符为单位,来写入数据,顶层抽象类是:Writer.

字节输出流(OutputStream)

1、概述

字节输出流指的是OutputStream,表示以字节为单位往文件中写入数据,但是**他是一个抽象类,**所以一般用他的子类,OutputStream类的常用子类如下:

FileOutputStream:普通的字节输出流.

BufferedOutputStream:高效的字节输出流.

2、FileOutputStream介绍

FileOutputStream表示普通的字节输出流, 用来以字节的形式将数据写入到指定的文件中.

3.1 构造方法

public FilePutputStream(String name)

解释:

​ 1.创建普通的字节输出流对象,关联目的地文件(字符串形式).

​ 2.如果文件中有数据,当程序启动之后并在文件中写入数据时**,文件已有的数据会被覆盖掉.**

pubulic FileOutputStream(File file)

解释:

​ 1.创建普通的字节输出流对象, 关联目的地文件(File对象形式).

​ 2.如果文件中有数据, 当程序启动之后并往文件中写入数据时, 文件中已有的数据会被覆盖掉.

public FileOutputStream(String name,boolean append)

解释:

​ 1.创建普通的字节数出流对象,关联目的地文件(字符串形式).

​ 2.当append为true时,表示往文件中追加数据,不会把原本的数据抹除.

public FileOutputStream(File file,boolean append)

解释:

​ 1.创建普通的字节输出流对象,关联目的地文件(File对象形式)

​ 2.当append的值为true的时候,表示往文件中追加数据,不会把原本的数据抹除.

3.2 成员方法

• public void write(int b)

解释: 一次写入一个字节, 到指定的目的地文件中.

• public void write(byte[] bys)

解释: 一次写入一个字节数组, 到指定的目的地文件中.

• public void write(byte[] bys, int start, int len)

解释: 一次写入一个字节数组的一部分, 到指定的目的地文件中.

• public void close()

解释: 关闭此文件输出流并释放与此流相关联的任何系统资源.

案例1 (FileOutputStream)

创建FileOutputStream对象, 关联指定的目的地文件. 往文件中写入字符’a’, ‘b’, ‘c’.

注意:

1 如果目的地文件不存在, 程序会自动创建.

2 如果目的地文件的路径不存在, 程序会报错.

public static void main(String[] args) throws IOException {
        //1. 创建FileOutputStream对象, 关联指定的目的地文件.
        //2. 往文件中写入字符'a', 'b', 'c'.
        FileOutputStream fos = new FileOutputStream("1.txt");
        //往文件中写入字符'a', 'b', 'c'.
        fos.write(97);
        fos.write(98);
        fos.write(99);
        //可以一次性写一个数组
        byte[] bys = {66,67,68};
        fos.write(bys);
        //一次写一个字节数组的一部分
        byte[] bytes = {66,67,68};
        fos.write(bytes,0,3);
        //释放资源
        fos.close();
    }1.txt中
abcBCDBCD

案例2: (\r\n)

通过上述的内容学习, 我们已经实现了往指定的文件中以字节(数组)的形式写入数据, 但是我们发现两个小问题:

上述写入目的地文件中的数据, 并没有换行

如果文件中有数据, 当我们启动程序又往文件中写入数据时, 之前的数据会被覆盖掉.

那如何解决上述的两个问题?

答案:

换行可以采用转移符**\r\n**来实现.

可以通过FIleOutputStream类的构造方法, 实现往目的地文件中追加数据的功能.

需求

创建FileOutputStream对象, 关联指定的目的地文件.

往文件中写入10次hello, 每个hello占一行.

往文件中追加一句话: 键盘敲烂, 月薪过万!

提示: 演示下\n, \r\n

public static void main(String[] args) throws IOException {
        FileOutputStream fos =new FileOutputStream("1.txt",true);
        for (int i = 0; i < 10; i++) {
            fos.write("hello\r\n".getBytes());
        }
        fos.close();
    }

案例2: 加入异常处理

需求

创建FileOutputStream对象, 关联指定的目的地文件.

往文件中写入如下内容: hello world!

演示通过try.catch.finally来解决异常.

public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("1.txt",true);
            fos.write("hello\r\n".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                if(fos != null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

案例4: 创造空文件

需求

在指定的路径下(例如: d:/abc)创建一个大小为1G的空文件.

public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("1.txt",true);
        byte[] bytes = new byte[1024];
        for (int i = 0; i < 1024*1024; i++) {
            fos.write(bytes);
        }
        fos.close();
        System.out.println("制造完成");
}

字节输入流(InputStream)

概述

字节输入流指的是InputStream,表示以字节为单位从文件后浓读取数据,但是他是一个抽象类,所以我们都是用他的子类,常用的两个子类为:

1.FileInputStream:普通的字节输入流.

2.BufferedInputStream:高效的字符输入流.

2、FileInputStream介绍

FileInputStream表示普通的字节输入流, 用来以字节的形式从文件中读取数据.

构造方法

• public FileInputStream(String name)

解释: 创建普通的字节输入流对象, 关联数据源文件(字符串形式).

• public FileInputStream(File file)

解释: 创建普通的字节输入流对象, 关联数据源文件(File对象形式).

成员方法

 public int read() 
 解释: 从指定的数据源文件中, 一次读取一个字节, 并返回该字节对应的整数. 读不到则返回-1.

 public int read(byte[] bys)
 解释: 
从指定的数据源文件中, 一次读取一个字节数组, 并将读取到的内容存入到字节数组中 .
返回读取到的有效字节数. 如果读不到则返回-1.

 public void close()
 解释: 关闭此文件输入流并释放与此流相关联的任何系统资源. 

案例1: FileInputStream入门

创建FileInputStream对象, 关联指定的数据源文件

通过一次读取一个字节的形式, 读取该文件中的数据

注意: 如果数据源文件不存在, 程序会报错

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");
        int len = 0;
        while((len = fis.read())  != -1){
            System.out.println(len);
        }
        fis.close();
    }

案例2: 一次读取一个字节数组

需求

创建FileInputStream对象, 关联指定的数据源文件.

通过一次读取一个字节数组的形式, 读取该文件中的数据.

 public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");
        int len = 0;
        byte[] bytes =new byte[3];
        while((len = fis.read(bytes))  != -1){
            System.out.println(new String(bytes,0,len));
        }
        fis.close();
    }

提示:做这个千万不要导错包了!!! 不然都写对了但是还是会飘红…

案例3: 复制文本文件

需求

将项目下的1.txt中的内容复制到2.txt文件中.

通过两种方式实现.

提示:

方式一: 一次读写一个字节.

方式二: 一次读写一个字节数组.

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");
        FileOutputStream fos = new FileOutputStream("2.txt");
    	//方式一
    	int len = 0;
        while((len = fis.read())  != -1){
          fos.write(len);
        }
        fis.close();
        fos.close();
        System.out.println("copy完成!");
        //方式二利用数组来进行快速copy
        int len = 0;
        byte[] bytes =new byte[1024];
        while((len = fis.read(bytes))  != -1){
          fos.write(bytes,0,len);
        }
        fis.close();
        fos.close();
        System.out.println("copy完成!");
    }

字节缓冲流

后面有个字符缓冲流(其实在字节上面修改的,本质也是字节,中国人用起来更方便,因为汉字更多)

概述

字节流一次读写一个字节数组的速度比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,

(本质也是一个数组),如果每次都是我们创建当然比较麻烦,所以java为我们提供了这样一个方法,叫做字节缓冲流

字节缓冲流也叫缓冲字节流, 高效字节流, 字节高效流, 它主要分为两个:

• BufferedInputStream: 字节缓冲输入流

• BufferedOutputStream: 字节缓冲输出流


构造方法

BufferedOutputStream类的构造方法

​ -public BufferedOutputStream(OutputStream os) 创建字节缓冲输出对象.

BufferedInputStream类的构造方法

​ -public BufferedInputStream(InputStream is) 创建字节缓冲输入流对象

为什么构造方法传递的是一个:OutputStream(或者InputStream),而不是具体的文件或者路径呢?

因为字节缓冲流仅仅提供缓冲区,真正的地城的读写数据还是需要基本的流对象进行操作

案例

案例1: 入门案例

需求

通过字节缓冲输出流往文件中写一句话.

通过字节缓冲输入流读取文件中的内容.

public static void main(String[] args) throws IOException {
        //读文件   input是读
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.txt"));

        //写文件   output是写
       // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.txt"));

        int len = 0;
        while ((len = bis.read()) != -1){
            //bos.write(len);
            System.out.println(len);//打印的是ASCII码表中所对应的数字
        }
       // bos.close();
        bis.close();

案例2 字节流复制视频

需求

分别通过四种方式拷贝视频文件, 并观察它们的效率.

通过普通的字节流一次读写一个字节的形式实现.

通过普通的字节流一次读写一个字节数组的形式实现.

通过高效的字节流一次读写一个字节的形式实现.

通过高效的字节流一次读写一个字节数组的形式实现.

public class Buffered {
    public static void main(String[] args) throws IOException {
        
        //普通字节流读一个字节
        //Copy1();
        //普通字节流读一个字节数组
        //Copy2();
        //字节高效流读取一个字节的形式表现
        //Copy3();
        //高效字节流读取一个字节数组的形式
        //Copy4();
   
    }

    private static void Copy4() throws IOException {
        //高效字节流读取一个字节数组的形式
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.txt"));
        int len = 0;
        byte[] bys =new byte[1024*8];
        while ((len = bis.read(bys)) != -1){
            bos.write(bys,0,len);
        }
        bos.close();
        bis.close();
    }

    private static void Copy1() throws IOException {
        //普通字节流读一个字节
        FileInputStream fis = new FileInputStream("1.txt");
        FileOutputStream fos = new FileOutputStream("2.txt");
        int len =0;
        while ((len =fis.read()) != -1){
            fos.write(len);
        }
        fos.close();
        fis.close();
    }

    private static void Copy2() throws IOException {
        //普通字节流读一个字节数组
        FileInputStream fis = new FileInputStream("1.txt");
        FileOutputStream fos = new FileOutputStream("2.txt");
        int len = 0;
        byte[] bys = new byte[1024];
        while ( (len =fis.read(bys)) != -1){
            fos.write(bys,0,len);
        }
        fos.close();
        fis.close();
    }

    private static void Copy3() throws IOException {
        //字符高效流读取一个字节的形式表现
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.txt"));
        int len =0;
        while ((len =bis.read()) != -1){
            bos.write(len);
        }
        bos.close();
        bis.close();
    }
}

字符流

概述

在IO开发过程中,我们传输最频繁的数据为字符,而以字节方式传输字符需要每次将字符串转换成字节再处理,而且也丧失了程序员对数据内容的判断(因为程序员只认识字符,不认识字节)。

所以,为了让程序员方便对字符进行操作,Java提供了专门以字符作为操作单位的类——字符流,其底层仍然为字节流。

显然,字符流只能操作字符,无法操作其他数据,如声音、视频等。

字符输出流:Writer类(写入)

Writer类

|----OutputStreamWriter

|----FileWriter类

注意:FileWriter类中的方法全部都是来自于父类

FileWriter类中的方法:

write(char ch) 一次写入一个字符

write(char[] cbuf, int off , int len) 一次向文件中写入多个字符数据。

说明:把char[]数组中从off角标开始取len长度个字符一次性写入

write(String str) 把字符串写入到文件中

write(String str, int off , int len) 写入字符串的某一部分

flush() 把字符输出流中内置缓冲区下的字节数据,写入到文件中(刷新流)

close() 由于每个IO流都需要绑定一个IO资源,在使用时,需要回收资源。而字符流输出流在关闭时,会先调用flush方法

public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("1.txt");
        fw.write('a');
        char[] arr ={'w','a','y'};
        fw.write(arr);
        fw.write(arr,1,2);
        fw.write("我爱大数据");
        fw.close();
    }
在当前目录下的1.txt文本中
awayay我爱大数据

字符输入流:Reader类(读取)

Reader:字符输入流的父类

|—InputStreamReder

|—FileReader:用来从文件中读取字符的输入流

FileReader类中的常用方法:

int read():读取一个字符; (使用int代替char)

int read(char[] c):读取一个字符数组;

close():由于每个IO流都需要绑定一个IO资源,在使用后,需要回收资源。

public static void main(String[] args) throws IOException {
        //写入数据
        //FileWriter fw = new FileWriter("1.txt");
        //fw.write('a');
        //char[] arr ={'w','a','y'};
        //fw.write(arr);
        //fw.write(arr,1,2);
        //fw.write("我爱大数据");
        //fw.close();
        //读取数据
        FileReader fr = new FileReader("1.txt");
        int len1;
        while ((len1 = fr.read())!= -1){
            System.out.print((char) len1);
        }
        fr.close();
        System.out.println("================");
        FileReader fr2 = new FileReader("1.txt");
        char[] arr =new char[1024];
        int len2;
        while ((len2 = fr2.read(arr)) != -1){
            System.out.println(new String(arr,0,len2));
        }
        fr2.close();
    }

字符流案例

案例: 复制文件

提示

通过普通的字符流, 即FileReader类和FileWriter类实现

需求

将项目下data文件夹中1.txt文件的内容, 拷贝到data文件夹下2.txt文件中.

运行, 并查看返回值结果.

参考代码

public class Demo03 {     public static void main(String[] args) throws IOException {         *//1. 创建输入流对象, 关联数据源文件.*        FileReader fr = new FileReader("day12/data/1.txt");             *//2. 创建输出流对象, 关联目的地文件.*        FileWriter fw = new FileWriter("day12/data/2.txt");            *//3. 定义变量, 记录读取到的内容或者有效字节(符)数.*        int len = 0;         *//4. 循环读取,只要条件满足就一直读, 并将读取到的内容赋值给变量.*        while ((len = fr.read()) != -1) {             *//5. 将读取到的内容写入到目的地文件中.*            fw.write(len);         }         *//6. 关流, 释放资源.*        fr.close();         fw.close();     } }

字符缓冲流

概述

字符流一次读写一个字符数组的速度比一次读写一个字符的速度快很多, 这是加入了数组这样的缓冲区效果, 但是如果每次都需要我们自己来定义数组的话, 是非常繁琐的. 所以Java本身在设计的时候, 也考虑到了这样的设计思想, 并提供了字符缓冲流.

字符缓冲流也叫缓冲字符流, 高效字符流, 字符高效流, 它主要分为两个:

BufferedReader: 字符缓冲输入流

BufferedWriter: 字符缓冲输出流

格式如下:

BufferedWriter类的构造方法

public BufferedWriter(Writer w) 创建字符缓冲输出流对象,

BufferedReader类的构造方法

public BufferedReader(Reader r) 创建字符缓冲输入流对象.

为什么构造方法传递的是一个: Writer (或者Reader ), 而不是具体的文件或者路径呢?

答案: 字符缓冲流仅仅提供缓冲区, 而真正的底层的读写数据还是需要基本的流对象进行操作.

与字节缓冲流极其类似 代码可以互相参考

案例一: 入门案例

需求

通过字符缓冲输出流往文件中写一句话.

通过字符缓冲输入流读取文件中的内容.

参考代码

BufferedReader br = new BufferedReader(new FileReader("2.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("3.txt"));
bw.write("11111111111111111111111111111111111");
int len1 = 0;
while ((len1 = br.read()) != -1){
    bw.write(len1);
}
bw.close();
br.close();

案例二: 字符流复制文件

通过字符缓冲流复制文件.

BufferedReader br = new BufferedReader(new FileReader("2.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("3.txt"));
int len1 = 0;
while ((len1 = fr.read()) != -1){
    fw.write(len1);
}
bw.close();
br.close();

案例: 字符缓冲流特有功能复制文件

补充

字符缓冲流在实际开发中用的非常多, 它也提供了两个非常常用的方法, 具体如下:

BufferedWriter类中的方法

public void newLine(); 根据当前操作系统, 给出对应的换行符.

BufferedReader类中的方法

public String readLine(); 读取一行数据, 只包含数据, 不包含任何终止字符, 如果读到流末尾, 则返回null. (只有这一个返回null)

需求

通过字符缓冲流一次读写一行的方式复制文件.

注意: 这种方式在实际开发中非常常用, 一定要掌握.

 BufferedReader br = new BufferedReader(new FileReader("2.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("3.txt"));
        String line ;
        while ((line = br.readLine()) != null){
            bw.write(line);
            bw.newLine();
        }
        bw.close();
        br.close();

序列化流

对象序列化流

解释:就是将对象保存在磁盘中,或者在网络中传输对象

这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息

字节序列写到文件之后,相当于文件中持久保存了一个对象的信息

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

对象序列化流: ObjectOutputStream

将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象

构造方法

方法名说明
ObjectOutputStream(OutputStream out)创建一个写入指定的OutputStream的ObjectOutputStream

序列化对象的方法

方法名说明
void writeObject(Object obj)将指定的对象写入ObjectOutputStream
//Student
package zifu_Output;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }

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


//测试类
public static void main(String[] args) throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("2.txt"));
    Student student = new Student("小李子",18);
    oos.writeObject(student);
    oos.close();
}

注意事项

一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口

Serializable是一个标记接口,实现该接口,不需要重写任何方法

对象反序列化流

对象反序列化流: ObjectInputStream

ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象

构造方法

方法名说明
ObjectInputStream(InputStream in)创建从指定的InputStream读取的ObjectInputStream

反序列化对象的方法

方法名说明
Object readObject()从ObjectInputStream读取一个对象
 public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("2.txt"));
        Student student = new Student("小李子",18);
        oos.writeObject(student);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("2.txt"));
        Object o =ois.readObject();
        Student s=(Student) o;
        System.out.println(s.toString());
        ois.close();
    }

serialVersionUID&transient

serialVersionUID

用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?

会出问题,会抛出InvalidClassException异常

如果出问题了,如何解决呢?

重新序列化

给对象所属的类加一个serialVersionUID

private static final long serialVersionUID = 42L;

transient

如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?

给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

示例代码

public class Student implements Serializable {
private static final long serialVersionUID = 42L;
private String name;
//    private int age;
private transient int age;

public Student() {
}

public Student(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;
}

//    @Override
//    public String toString() {
//        return "Student{" +
//                "name='" + name + '\'' +
//                ", age=" + age +
//                '}';
//    }
}
//测试类
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//        write();
read();
}

//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}

//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));
Student s = new Student("林青霞", 30);
oos.writeObject(s);
oos.close();
}
}

写在最后
希望自己能够一直坚持下去,加油!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值