I/O流的理解与应用

IO流概述

IO是Input和Output的缩写

两个单词一个表示输入,一个表示输出。表示的是数据的输入和数据的输出。

相对于运行内存来说,【数据从其他地方进入运行内存,就是输入

​ 【数据从运行内存到其他地方,就是输出

IO:表示的不是一个特定的类型,表示的是数据的输入和输出的概念

在这里插入图片描述

IO流分类

  • 按照功能分类
    • 字节流:控制字节信息输入和输出
    • 字符流:控制字符信息的输入和输出
  • 按照流向分类
    • 输入流:控制信息从其他设备到运行内存
    • 输出流:控制信息从运行内存到其他设备

具体分类:

  • 字节输入流:InputStream
  • 字节输出流:OutputStream
  • 字符输入流:Reader
  • 字符输出流:Writer

字节流

概述:用来操作字节信息输入内存和输出内存

字节输入流 InputStream

字节输出流 OutputStream

InputStream

概述:字节输入流,本类是一个抽象类,不能直接创建对象,需要通过子类创建

方法

  • read() :从流中读取一个字节信息,将读取的信息进行返回。

    • 该方法的返回值是int值:因为默认将读取的每个byte字节强制转为了int类型。

    • 如果不转为int类型,而是使用byte类型直接接收,那么byte表示的范围为:-128—127,如果读取了一个信息为-1.-1是到达文件末尾还是读取的字节数据,不能区别,所以就将读取的每个字节统统转为int,一旦转为int类型之后,不管读取的信息是负数还是整数,结果都是为正数,当在读取到一个-1时,表示肯定时文件到达末尾。

  • read(byte[] b) :从流对象中一次读取b.length个字节

    将读取的信息保存在数组中,返回的是读取的个数

  • read(byte[] b, int off, int len) :从流中读取指定长度的数据到数组中将读取的信息保存在数组中,返回的是读取的个数

  • available() :将流中还没有读取的字节个数进行返回

  • close() :关闭流资源

FileInputStream

概述:属于字节输入流的子类,该类的对象可以将磁盘上的文件数据读取到运行内存中

构造方法

  • FileInputStream(File file):将file文件对象封装为文件字节输入流对象
  • FileInputStream(String str) :将str字符串所描述的文件封装为字节输入流对象

注意

  • 指定路径时,文件的路径要存在
  • 给定的路径一定要是文件的路径,不能时文件夹,因为文件中才可以保存数据

代码:

//chen.txt中的文件

一个一个返回:

    //创建文件路径
    File f = new File("18day/src/chen.txt");
    //造输入流
    FileInputStream fis = new FileInputStream(f);
    int i;
    //循环输出,强转为char类型
    while ((i = fis.read()) != -1) {
        System.out.print((char) i + " ");
    }
    //关闭系统资源
       fis.close();
//c h e n s h u a n g 

返回数组,一组一组返回

    //创建文件路径
    File f = new File("18day/src/chen.txt");
    //造输入流
    FileInputStream fis = new FileInputStream(f);
    byte[] c = new byte[13];
    int i= fis.read(c);
    System.out.println(Arrays.toString(c));
    //关闭系统资源
    fis.close();
//[99, 104, 101, 110, 115, 104, 117, 97, 110, 103, 0, 0, 0]

OutputStream

概述:字节输出流,将字节信息从内存中写出到其他设备。也是一个抽象类,需要通过 子类创建对象。

方法

  • write(int b) :将一个字节信息写出内存
  • write(byte[] b) :将一个数组中的信息写出内存
  • write(byte[] b, int off, int len) :将数组中的一部分信息写出内容
  • close() :关闭流资源
FileOutputStream

概述:文件字节输出流,将字节信息从内存中写出到目标磁盘文件中。

构造方法

  • FileOutputStream(File file) :将file对象封装为一个字节输出流对象
  • FileOutputStream(String name) :将name字符串对应的文件封装为字节输出流对像
  • FileOutputStream((File file,boolean b) :将name字符串对应的文件封装为字节输出流对 象,如果后面的值为false,表示替换写入信息
  • FileOutputStream(String name,boolean b) :将name字符串对应的文件封装为字节输出流对象,如果后面的值为true,表示追加写入信息

注意在写出信息时,写出的路径一定是文件的路径不能是文件夹路径

public static void main(String[] args) throws IOException {
    //造文件,写入的指定文件
    File f = new File("18day/src/c.txt");
    //造流
    FileOutputStream fos = new FileOutputStream(f);
    //一个字符一个字符的写入
    fos.write(97);
    //fos.write('c'); //char - int - byte

    //直接写入一个数组
    byte[] by = {1,2,4,63,34,};
    fos.write(by);
    //只写入数组中的前三个字节
    fos.write(by,0,3);

    //关闭系统资源
    fos.close();
}

文件的拷贝

概述:将一个文件中的内容,全部复制到另外一个文件中。

思路:先读取源文件中的数据,然后再将读取的数据写出到另外一个文件中

图示原理

在这里插入图片描述

//要赋值的文件路径
File f1 = new File("18day/src/chen.txt");
//目的路径
File f2 = new File("18day/src/c.txt");

//造输入输出流
FileInputStream fis = new FileInputStream(f1);
FileOutputStream fos = new FileOutputStream(f2);

//循环写入
int i ;
while ((i=fis.read())!=-1){
    fos.write(i);
}

//关闭系统资源
fis.close();
fos.close();

拷贝效率的提升

  • 为什么需要提升效率

    • 当需要拷贝一个文件,该文件的大小过大,拷贝的时间就非常久。

      因为一个字节需要IO两次

  • 提升的方式

    • 每次可以多读入几个字节,多写出几个字节。

    • 可以准备一个数组,数组的大小为:文件的字节大小

      使用数组的方式,一次读取完毕,一次写出完毕即可

    • 优点:一次读取一次写出,时间短,效率高

    • 缺点:如果需要创建的数组大小过大,对运行内存的要求久比较高,一旦数组的大小超 过了或者临近运行内存,那么久可能出先一些内存不够的问题。

  • 最终方案:使用小数组拷贝

    • 使用数组来进行读取和写出,但是数组空间不需要创建那么大,一次虽然拷贝不完,但 是也比一个个拷贝要快。
    • 使用小数组注意:每次读取几个字节,就应该写出几个字节,避免数据写出重复

代码:

private static void test02() throws IOException {
    //要赋值的文件路径
    File f1 = new File("18day/src/chen.txt");
    //目的路径
    File f2 = new File("18day/src/c.txt");

    //造输入输出流
    FileInputStream fis = new FileInputStream(f1);
    FileOutputStream fos = new FileOutputStream(f2);

    //利用数组循环写入,提高效率
    byte[] by = new byte[10];
    int i ;
    while ((i=fis.read(by))!=-1){
        fos.write(by,0,i);
    }

    //关闭系统资源
    fis.close();
    fos.close();
}

高效缓冲字节流

高效缓冲字节输入流:BufferedInputStream

高效缓冲字节输出流:BufferedOutPutStream

  • 构造方法

    • BufferedInputStream(InputStream in) :将基础的字节输入流对象进行包装成为一个高效 字节输入流
    • BufferedOutputStream(OutputStream out) :将基础的字节输出流对象进行包装
  • 三种拷贝方式原理对比

在这里插入图片描述

private static void test02() throws IOException {
    //要赋值的文件路径
    File f1 = new File("18day/src/chen.txt");
    //目的路径
    File f2 = new File("18day/src/c.txt");

    //造输入输出流--加入高校缓冲字节流
    FileInputStream fis = new FileInputStream(f1);
    FileOutputStream fos = new FileOutputStream(f2);
    BufferedInputStream bis = new BufferedInputStream(fis);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    
    //利用数组循环写入,提高效率
    byte[] by = new byte[10];
    int i ;
    while ((i=bis.read(by))!=-1){
        bos.write(by,0,i);
    }

    //关闭系统资源,关闭缓冲字节流资源的时候,字节流的也被关闭
    bis.close();
    bos.close();
}

close和flush方法的区别

  • 两个方法都可以将数据从缓冲区刷新到目标文件中
  • 不同点
    • close不仅可以刷新数据进入目标文件,还可以关闭系统资源
    • flush只能用来刷新数据进入目标文件

字符流

使用字符流的原因

  • 如果想要读取文件中的信息,这个文件中信息全部英文,可以使用字节流一次读取一个 字节,进行转码展示。
  • 如果文件中的信息,是全中文,可以每次读取三个或者两个,将读取的三个或者两次字 节也可以转成字符串展示。
  • 如果文件中的信息,是中英文混杂,每次读取几个字节就不确定,就有可能出现乱码。
  • 如果要写出一些字符串,没法直接通过字节流写出,需要先将这个字符串转为字节数组 才可以写出,每次都进行转换,浪费时间,也浪费空间。

概述

  • 字符流:可以以字符为单位操作数据的输入和输出的对象所属的类型

  • 分类:

    字符输入流 Reader

    字符输出流 Writer

Reader

字符输入流:也是一个抽象父类,不能直接创建对象

方法

  • read() :读取一个字符信息,将读到的信息进行返回
  • read(char[] c) :读取c.length个字符到数组中,返回的是读取的字符个数
  • read(char[] c,in t offset,int len):读取一部分字符到数组中
  • close() :关闭流资源

使用子类创建对象FileReader

  • FileReader(File file)
  • FileReader(String fileName)
//创建文件路径
File f = new File("18day/src/chen.txt");
//造字符输入流
FileReader fr = new FileReader(f);
char[] c = new char[10];
int len = fr.read(c);
System.out.println(c);
//关闭系统资源
fr.close();

Writer

字符输出流,是一个抽象父类,不能直接创建对象

方法:

  • write(int c) :写出一个字符
  • write(String str) :写出一个字符串
  • write(char[] cbuf) :写出一个数组中的字符
  • write(char[] cbuf, int off, int len) :写出数组的一部分到目标文件
  • write(String str, int off, int len) :写出字符串的一部分
  • close()

FileWriter:文件字符输出流

  • FileWriter(File file)
  • FileWriter(String fileName)
public static void main(String[] args) throws IOException {
    //创建文件路径
    File f = new File("18day/src/chen.txt");
    //造流----true:表示可以在文件上继续追加内容
    FileWriter fw = new FileWriter(f,true);

    fw.write('c');
    fw.write("chen");
    fw.write(new char[]{'a','b','c'});
    fw.write(new char[]{'a','b','c'},0,2);
    fw.write("我还好!",0,2);
    
    //关闭系统资源
    fw.close();
}
//chen.txt文件
cchenabcab我还

使用字符流拷贝文件

  • 使用字符流一样可以拷贝文本文件
  • 原理

在这里插入图片描述

  • 区别使用
    • 如果以后仅仅是为了拷贝文件,使用字节流来拷贝
    • 如果后续需要查看文件的内容,或者要写出内容,使用字符流来完成

字符流不可以拷贝非纯文本文件

  • 纯文本文件:文件中的信息全都是通过字符组成

  • 非纯文本文件:比如:视频 音频 图片

  • 为什么字符流不能拷贝非纯文本文件

    因为非纯文本文件中的字节可能在编码表中没有对应字符信息,如果读取一个字节,没 有字符与之对应,在解码时,就会将这个没有对应字符的字节通过?字符来代替,再写 出的时候,写出的是?字符对应的字节,这一步对信息发生了篡改,就导致文件的数据 拷贝错误,源文件的内容可能再拷贝之后就无法使用。

高效缓冲字符流

类型:BufferedReader和BufferedWriter

概述:都是包装类型,需要对基础的字符流对象进行包装。包装之后,一次也可以读取 多个字 符,可以写出多个字符。

构造BufferedReader(Reader in)

  • 方法:readLine()

    一次可以从输入流中读取一行信息

​ 返回值就是读取的这一行数据,如果到达文件的末尾,返回null

构造BufferedWriter(Writer out)

  • 方法:newLine() :表示在文件中进行换行
    在这里插入图片描述

转换流

转换输入流和转换输出流

OutputStreamWriter:转换输出流,在输出数据时,可以指定编码格式

  • 构造方法:OutputStreamWriter(OutputStream in, Charset cs) 使用基础的输出流对象,指定以cs 编码格式来写出信息
public static void main(String[] args) throws IOException {
        //创建转换输入流
        InputStreamReader isr = new InputStreamReader(new 				                       FileInputStream("19day/src/note/zhuanhuan/c.txt"),"UTF-8");
        int i;
        while ((i= isr.read())!=-1){
            System.out.println(i);
        }
        isr.close();
    }

InputStreamReade:转换输入流,在输入数据时,可以指定编码格式

  • 构造方法:InputStreamReader(InputStream in, Charset cs) :使用基础的输入流对象,指定以cs编码 格式读取信息
 public static void main(String[] args) throws IOException {
        //创建转换输出流
        OutputStreamWriter osw = new OutputStreamWriter(new 		                           FileOutputStream("19day/src/note/zhuanhuan/c.txt"),"UTF-8");
        osw.write("aaabbbccc");
        osw.close();
    }

注意

  • 当读取信息时,应该以源文件的编码格式读取信息(解析信息)
  • 当写出信息时,应该以目标文件的编码格式写出信息
  • 不管是转换输入流还是转换输出流,都是字符流
  • 转换流也是字节流到字符流的桥梁
public static void main(String[] args) throws IOException {
    //创建转换输入流  被复制文件编码格式为 GBK
    InputStreamReader isr = new InputStreamReader(new FileInputStream("19day/src/note/zhuanhuan/a.txt"),"GBK");
    //创建转换输出流  目标文件编码格式为 UTF-8
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("19day/src/note/zhuanhuan/c.txt"),"UTF-8");

    int i;
    while ((i= isr.read())!=-1){
        osw.write(i);
    }
    //关流
    isr.close();
    osw.close();
}

标准输入流输出流

标准输入流

概述:System.in

  • 该流的类型为InputStream,属于是字节流
  • 默认关联的设备为键盘,即数据源为键盘
  • 一般该输入流和Scanner类型一起用更方便
//本身为一个字节输入流
InputStream is =System.in;
int i = is.read();
System.out.println(i);
/*
a
97
public static void main(String[] args) throws IOException {
    InputStream is = System.in;
    //可以将字节输入流加强为字符流
    InputStreamReader isr = new InputStreamReader(is);
    //可以将字符流加强为高效流
    BufferedReader br = new BufferedReader(isr);
    //使用高效流可以从控制台输入字符串
    String s = br.readLine();
    System.out.println(s);
    br.close();
}
/*
aaabbb
aaabbb
  • 通过**System.setIn(InputStream in)**方法,可以更改标准输入流关联的设备
//System.in 默认为从键盘录入的数据
//使用setIn方法后可以更改 读取的数据源
System.setIn(new FileInputStream("19day/src/c.txt"));
InputStream is = System.in;
int i = is.read();
System.out.println(i);
/* 
65(c.txt中内容为A)

标准输出流

概述:System.out

  • 该流的类型为PrintStream,其父类为OutputStream是一个字节输出流
  • 默认关联的设备为控制台,即数据目的地为控制台
//System.out本身也是一个字节输出流
OutputStream os = System.out;
os.write(2);
os.write('c');
os.write('我');
os.close();
//可以对该输出流进行加强,加强为字符流
//加强之后可以在控制台输出字符串
OutputStream os = System.out;
OutputStreamWriter osw = new OutputStreamWriter(System.out);
osw.write("aaabbbc");
osw.close();
//aaabbbc
  • 通过System.setOut(PrintStreamout)方法,可以更改标准输出流关联的设备
//System.out默认将数据打印在控制台
//可以通过 setOut方法修改
//修改之后,后续在使用这个流写出信息时不会写出到控制台,二十指定的位置
OutputStream os = System.out;
System.setOut(new PrintStream("19day/src/c.txt"));
OutputStreamWriter osw = new OutputStreamWriter(System.out);
osw.write("aaabbbc");
osw.close();
//c.txt中写入aaabbbc

打印流

打印流介绍

  • 打印流分为打印字节流和打印字符流:

    PrintStream 打印字节流 字节输出流

    PrintWriter 打印字符流 字符输出流

  • 打印流属于输出流。

打印字节流

PrintStream:是OutPutStream的间接子类,是一个输出流,也是一个字节流

构造方法

  • PrintStream(File file) :创建具有指定文件的新打印流。
PrintStream ps = new PrintStream("19day/src/c.txt");
  • PrintStream(String fileName) :创建指定文件路径的新打印流。
PrintStream ps = new PrintStream("19day/src/c.txt");
  • PrintStream(OutputStream out):将一个字节流对象,封装为一个打印流

常用方法

  • 从父类中继承的方法:write()

    注意:只可以写出一个字节信息

  • 自己特有的方法print println

    不仅可以输出字节信息,还可以输出各种数据类型的信息

    比如:整数、小数、字符、字符串、对象

PrintStream ps =new PrintStream(new FileOutputStream("19day/src/c.txt"));
//可以使用普通的字节输出流写出信息
ps.write(1);
ps.write('a');
//也可以使用特有的方法来写出信息 println  print方法【可以写出各种类型的数据】
ps.println(true);
ps.println('c');
ps.println(88);
ps.println("aaa");
ps.println(100.2);
ps.println(new Person("aaa",22));

ps.close();
/*c.txt内容为:
atrue
c
88
aaa
100.2
Person{name='aaa', age=22}

打印字符流

PrintWriter:是Writer的间接子类,是一个输出流,也是一个字符流

构造方法

  • PrintWriter (File file) :创建具有指定文件的新打印流。
  • PrintWriter (String fileName) :创建指定文件路径的新打印流。
PrintWriter pw = new PrintWriter("19day/src/c.txt");
  • PrintWriter(OutputStream out):将一个字节流封装为一个打印字符流
  • PrintWriter(Writer out) :将一个字符流封装为一个打印流
  • PrintWriter(OutputStream out,boolean b):将一个字节流封装为一个打印字符流【可以实现自动刷新功能】
  • PrintWriter(Writer out,boolean b) :将一个字符流封装为一个打印流【可以实现自动刷新功能】

常用方法

  • 从父类中继承的方法:write()

    注意:可以写出一个字符,也可以写出一个字符串

  • 自己特有的方法print println

//打印流在创建对象时,可以传递一个布尔值来实现数据的自动刷新
PrintWriter pw = new PrintWriter(new FileWriter("19day/src/c.txt"));
pw.println("aaa");
pw.println('c');
pw.println(88);
pw.println(new Person("aaa",23));

pw.close();
/*c.txt内容为:
aaa
c
88
Person{name='aaa', age=23}

对象序列化流

相关概念

数据的状态

  • 游离态:在运行内存中的运行的数据。随着程序的结束,数据也会被回收
  • 持久态:在磁盘中进行保存的数据。随着程序的结束,随着计算机的关机和开机,数据并不会消失。

序列化

  • 将数据从运行内存中 ===> 到磁盘中

    数据从游离态===>持久态 (输出)

反序列化

  • 将数据从磁盘中 ===> 到运行内存中

    持久态===>游离态 (输入)

【对象序列化流的使用】

构造方法

  • ObjectOutputStream(OutputStream out)将一个输出流,封装为一个对象序列化流

序列化对象方法:

  • writeObject(Object obj)将指定对象写出到流中传输

  • 将对象实现序列化之后,文件的内容看不懂,是正常情况,因为保存的是一个个对象数据,而不是字符串。

  • 如果需要将一个类型的对象实现序列化,那么该类型就需要实现一个接口:

    Serializable:序列化接口(标记型接口)

    该接口没有任何方法需要重写,只需要让类型实现接口,就可以实现序列化和反序列化。

//学生类实现Serializable接口
public class Student implements Serializable {
    private String name;
    private int age;

//创建序列化输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("19day/src/c.txt"));
//造对象
Student s1 = new Student("aaa", 23);
oos.writeObject(s1);
oos.close();

多个对象的时候放在集合中

//造对象
Person p = new Person("陈爽",23);
Person p1 = new Person("陈爽",23);
//创建person类型的集合
ArrayList<Person> list = new ArrayList<>();
//创建对象序列化流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("19day/src/xuliehua/chen.txt"));
//把对象先保存在集合对象中
list.add(p);
list.add(p1);
//使用特殊方法将集合对象写入到指定文件中
oos.writeObject(list);
oos.close();

【反序列化的使用】

构造方法

ObjectInputStream(InputStream inp):将一个输入流,封装为一个对象序列化流

反序列化对象方法readObject():将对象从文件中读取到内存中

注意事项

  • 读取文件中的对象时,注意如果文件中数据读取完毕,继续读取出现:EOFException
  • 当需要序列化多个对象时,一般将这多个对象先保存在集合对象中,只需要序列化一个集合对象即可。后续在反序列化的时候,也只需要读取一次,读取的是集 合对象,然后可以遍历读取的集合依次获取每一个保存的对象。
  • 当类型需要参与序列化和反序列化,一般都给定一个固定的序列化ID给定之后,后续就可以随意对类型进行修改,即使修改了也不影响对象的序列化或者反序列化
//创建反序列化输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("19day/src/c.txt"));
Object o = ois.readObject();
System.out.println(o);
//Student{name='aaa', age=23}

多个对象的时候遍历集合获取

    //创建反序列化流
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("19day/src/xuliehua/chen.txt"));
     //使用方法,把集合对象读取到程序中
    ArrayList<Student> list = (ArrayList<Student>)ois.readObject();
    //循环遍历
    for (Student p:list){
        System.out.println(p);
    }
    ois.close();
//Student{name='陈爽', age=23}
//Student{name='陈爽', age=23}

transient关键字

1、在实现对象的序列化和反序列化时,如果某些特定的属性不需要参与,就可以通过关键 字:transient来修饰该属性,一旦属性被关键字修饰之后,就不参与读取和写出。

public class Student implements Serializable {
    private transient String name;

Properties

是一个双列集合,是一个Map体系的集合类,是Hashtable的子类

properties特殊方法

  • setProperty(String key, String value):添加键值对
  • getProperty(String key):根据指定的键获取对应的值
  • stringPropertyNames():将集合中的键获取到一个单列集合Set中进行存储

Properties和IO流相结合的方法

  • store(Writer writer, String comments):将此属性列表(键和元素对)写入Properties文件
  • store(OutputStream out, String comments) :将此属性列表(键和元素对)写入Properties
//创建一个Properties的集合类
Properties pro = new Properties();
pro.setProperty("aaa","23");
pro.setProperty("bbb","24");
pro.setProperty("ccc","25");
//把该集合中的每个键值对数据,输出保存在一个文件中
//参数一:给定一个输出流
//参数二:写出信息时,给出注释,不能不屑,但是可以为空
pro.store(new FileWriter("19day/src/c.txt"),"null");
//c.txt中内容
#null
#Tue Mar 08 21:27:50 CST 2022
bbb=24
aaa=23
ccc=25
  • load(Reader reader):从输入字符流读取属性列表(键和元素对)
  • load(InputStream in):从输入字节流读取属性列表(键和元素对)
//创建一个集合
Properties pro = new Properties();
//将某个文件中的键值对保存到集合中使用
pro.load(new FileReader("19day/src/c.txt"));
System.out.println(pro);

//{bbb=24, aaa=23, ccc=25}

案例1:

(1) 在Properties文件中有如下信息:

​ name=张三

​ age=18

​ hobby=玩游戏

(2)将数据读取到集合中

(3)将读取的数据封装成一个学生对象,将该对象输出为本地文件中永久保存

private static void ex01() throws IOException, ClassNotFoundException {
    Properties pro = new Properties();
    //把键值对下载到集合
    pro.load(new FileReader("19day/src/properties/Properties.txt"));
    //把键值对的信息创建对象--提前写好学生类并实现Serializable接口
    Student stu = new Student(pro.getProperty("name"), pro.getProperty("age"), pro.getProperty("hobby") );
    //创建序列化流
    ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream("19day/src/properties/chen.txt"));
    //把集合键值对写入到
    oos.writeObject(stu);
    //关流
    oos.close();
}

案例二:

​ 在Properties文件中有如下信息:

​ name=张三

​ age=18

​ hobby=玩游戏

(2)将该文件中的name=张三,改为name=李四

(3)要求:使用代码完成内容的修改

private static void test02() throws IOException {
    Properties pro = new Properties();
    pro.load(new FileReader("19day/src/properties/Properties.txt"));
    pro.setProperty("name","李四");
    pro.store(new FileWriter("19day/src/properties/Properties.txt"),"null");
}

关流方式

JDK1.7版本之前的关流方式

public static void main(String[] args) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("19day/src/c.txt");
            fos = new FileOutputStream("19day/src/c.txt");
            int i;
            while ((i = fis.read()) != -1) {
                fos.write(i);
            }
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } finally {
                    if (fos != null) {
                        fos.close();
                    }
            }
        }
    }
}

JDK1.8之后的关流方式

try(
FileInputStream fis =new FileInputStream("19day/src/c.txt");
FileOutputStream fos = new FileOutputStream("19day/src/c.txt");
) {
    int i;
    while ((i = fis.read()) != -1) {
        fos.write(i);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡丘不断更

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值