java-IO流

IO流

java-IO流

1.输入流与输出流

  • 流:数据在数据源(文件)和程序(内存)之间的路径
  • 输入流:数据从数据源(文件)到程序(内存)的路径
  • 输出流:数据从程序(内存)到数据源(文件)的路径

java-IO流

常用的文件操作

File类实现了SerializableComparable接口

File类的构造器

new File(String pathname)//根据路径构建一个File对象

new File(File parent,String pathname)//根据父目录文件+子路径构建一个File对象

new File(String parent,Sting child)//根据父路径+子路径构建一个File对象

new File (URI uri)//通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。

 public static void main(String[] args) throws IOException, URISyntaxException {
        File file1=new File("d:/news1.txt");
        File file2=new File("d:\\","news2.txt");
        File file3=new File("d:\\");
        File file4=new File(file3,"news3.txt");
        URI uri=new URI("file:///d:/news4.txt");
        File file5= new File(uri);
        //上面的file1、file2..等  只是在java中的一个对象
        //只有执行了 createNewFile()方法,才会真正在磁盘中创建该文件        if(file1.createNewFile()&&file2.createNewFile()&&file4.createNewFile()&&file5.createNewFile()){
            System.out.println("文件创建成功!");
        }else {
            System.out.println("文件创建失败!");
        }
    }

File对象常用的一些方法

  • file.getName()//返回由此抽象路径名表示的文件或目录的名称。
  • file.getAbsoluteFile()//返回此抽象路径名的绝对路径名形式。返回类型是File
  • file.getAbsolutePath()//返回此抽象路径名的绝对路径名字符串。返回类型是String
  • file.getParent()//返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null
  • file.length()//返回由此抽象路径名表示的文件的长度。
  • file.exists()//测试此抽象路径名表示的文件或目录是否存在。
  • file.isFile()//测试此抽象路径名表示的文件是否是一个标准文件。
  • file.isDirectory()//测试此抽象路径名表示的文件是否是一个目录。
  • file.mkdir()// 创建此抽象路径名指定的目录(一级目录)。
  • file.mkdir()//创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。(创建多级目录)

流的分类

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

字节输入流(InputStream)常用的子类

  1. FileInputStream:文件输入流
  2. BufferedInputStream:缓冲字节输入流
  3. ObjectInputStream:对象字节输入流

2.字节流

FileInputStream

/**
 * 单个字节读取效率低
 */
public void read01()  {
    String path="d:\\news1.txt";
    FileInputStream fileInputStream=null;
    try {
        fileInputStream=new FileInputStream(path);
        int read = 0;
       while ((read=fileInputStream.read())!=-1){
           System.out.print((char) read);
       }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        //关闭文件流,释放资源
        try {
            fileInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public void read2(){
    String path="d:\\news1.txt";
    FileInputStream fileInputStream=null;
    //定义字节数组
    byte[] buf=new byte[8];
    try {
        fileInputStream=new FileInputStream(path);
        int readLen= 0;
        //fileInputStream.read(buf) 如果读取正常返回实际读取的字节数  每次最多读8字节
        //如果返回-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 (IOException e) {
            e.printStackTrace();
        }
    }
}

FileOutPutStream

public class OutPutStream_ {
    public static void main(String[] args) {
new OutPutStream_().writeFile();
    }
    public void writeFile(){
        String filePath="d:\\news.txt";
        FileOutputStream fos=null;
        try {
            //若没有该文件,则会自动创建
            fos=new FileOutputStream(filePath);
     /**
        * 1、new FileOutputStream(filePath);这种创建方式,当写入内容时,会覆盖其内容
        * 2、new FileOutputStream(filePath,true);这种方式创建,当写入内容时,会以追加的方式,不会覆盖原内容
       */
            //写入一个字节
            fos.write('a');
            String str="wanna";
            //将字符串转化为字符数组  str.getBytes()
            fos.write(str.getBytes());
            /**
             * write(byte[] b, int off, int len)
             * 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
             */
            fos.write(str.getBytes(),0,3);//截取前三个字节写入
        }  catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

两者结合使用 拷贝文件

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

public class FileCopy {
    public static void main(String[] args) {
        FileInputStream fis=null;
        FileOutputStream fos=null;
        String filePath="d:\\a.jpg";
        String destFilePath="c:\\a.jpg";
        byte[] bytes=new byte[1024];
        int readLen=0;
        try {
            fis=new FileInputStream(filePath);
            fos=new FileOutputStream(destFilePath);
            while ((readLen=fis.read(bytes))!=-1){
                fos.write(bytes,0,readLen);//一定要使用这个方法
            }
            System.out.println("拷贝完成!");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            if (fos != null) {
                fos.close();
            }
        }catch (IOException e){
            e.printStackTrace();
            }
        }
    }
}

3.字符流

FileReader与FileWriter

FileReader与FileWriter都是字符流,按照字符操作IO

FileReader

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

public class FileReader_ {
    public void reader01(){
        FileReader fileReader=null;
        try {
            fileReader=new FileReader("d:\\news.txt");
            int data=0;
            while ((data=fileReader.read())!=-1)
            {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {

                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public void reader02(){
        FileReader fileReader=null;
        try {
            fileReader=new FileReader("d:\\news.txt");
            int data=0;
            char[] chars=new char[5];
            while ((data=fileReader.read(chars))!=-1)
            {
                System.out.print(new String(chars,0,data));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {

                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
new FileReader_().reader02();
    }
}

FileWriter

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

public class FileWriter_ {
    public void Writer01(){
        String filePath="d:\\news.txt";
        FileWriter fw=null;
        try {
            fw=new FileWriter(filePath);
            /**
             *
             *  void write(char[] cbuf, int off, int len)
             *           写入字符数组的某一部分。
             *  void write(int c)
             *           写入单个字符。
             *  void write(String str, int off, int len)
             *           写入字符串的某一部分。
             */
            String str="你好这是void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。\n";
            fw.write(str.toCharArray(),0,20);
            fw.write(77);
            fw.write('o');
            fw.write("\n这是FileWriter......");
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                /**
                 * 对于FileWriter,一定要关闭或者刷新流,才能将数据写入文件!!!!
                 * flush()与close()在底层实现上都掉用了writeBytes()  才将数据写入文件
                 */
                fw.flush();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) {
        new FileWriter_().Writer01();
    }
}

4.节点流与处理流

基本介绍

1.节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter(对文件读写)等。还有一些是对管道、数组等进行读写操作。

2.处理流也叫包装流是连接已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter。

两者的区别与联系:

  • 节点流是底层流/低级流,直接和数据源相连
  • 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法完成输入输出。
  • 处理流(也叫包装流)是对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连。

字符处理流:

BufferedReader与BufferedWriter属于字符流,按照字符来读取数据。所以不适合读取二进制文件。

BufferedReader

package Reader_;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReader_ {
    public static void main(String[] args) {
        String filePath="d:\\news.txt";
        BufferedReader bufferedReader=null;
        try {
             bufferedReader = new BufferedReader(new FileReader(filePath));
            String line;//按行读取
            /**
             * bufferedReader.readLine  按行读取
             * 当返回为null时读取完毕
             */
         ;
            while (( line=bufferedReader.readLine())!=null){
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                /**
                *这里不需要关闭 FileReader
                *只需要关闭外层包装流,它会调用你穿进来的流的close()方法
                */
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

BufferedWriter

package Writer_;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath="d:\\news1.txt";
        /**
         * new FileWriter(filePath,true) 是以追加的方式进行写入
         * new FileWriter(filePath)是以覆盖的方式写入
         */
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
        bufferedWriter.write("祝大家百万年薪!!!");
        bufferedWriter.newLine();//插入一个和系统相关的换行
        bufferedWriter.write("我们都是打工人!!!");
        /**
         * 这里关闭外层包装流即可,它会在底层调用 你传进来的流的close方法
         */
       // bufferedWriter.flush();
        bufferedWriter.close();
    }
}

使用BufferedWriter与BufferedReader拷贝文件

package Copy;

import java.io.*;

public class BufferedCopy_ {
    public static void main(String[] args) throws IOException {
        String srcPath="d:\\news.txt";
        String destPath="d:\\news2.txt";
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destPath));
        BufferedReader bufferedReader=new BufferedReader(new FileReader(srcPath));
        String line=null;
        while ((line=bufferedReader.readLine())!=null){
            //每读入一行就写入 同时加上换行
            bufferedWriter.write(line);
            bufferedWriter.newLine();
        }
        //关闭流
        if (bufferedReader!=null){
            bufferedReader.close();
        }
        if (bufferedWriter!=null){
            bufferedWriter.close();
        }
    }
}

字节处理流:

BufferedInputStream与BufferedOutStream属于字节流,可以用来进行二进制文件(音频、视频、pdf、word…)的读写。

使用BufferedInputStream与BufferedOutStream拷贝文件

package Copy;
import java.io.*;
public class BufferedCopy_02 {
    public static void main(String[] args)  {
        String srcPath="d:\\news.txt";
        String destPath="d:\\news3.txt";
        BufferedOutputStream bos=null;
        BufferedInputStream bis=null;
        try {
            bos=  new BufferedOutputStream(new FileOutputStream(destPath));
            bis =new BufferedInputStream(new FileInputStream(srcPath));
            byte[] bytes=new byte[1024];
            int readline=0;
           while( (readline=bis.read(bytes))!=-1){
               bos.write(bytes,0,readline);
           }
            System.out.println("拷贝完成!!");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                /**
                 * 同理也是关闭外层流
                 */
            if (bis!=null){
                bis.close();
            }if (bos!=null){

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

    }
}

5.对象流

对象流:ObjectInputStream和ObjectOutputStream

对一个对象的数据及类型进行保存

这就牵扯到 序列化与反序列化

序列化 :就是在保存数据时,保存数据的值与数据类型。

反序列化:就是在恢复数据时,恢复数据的值与数据类型。

要让对象支持序列化机制,必须让其类是可序列化的,这个类必须实现以下两个接口之一:

  • Serializable(推荐使用):这是一个标记接口,标记该类可以系列化,它里面没有任何方法。
  • Externalizable:它继承了Serializable接口,有一些扩充方法,需要实现这些方法。

ObjectInputStream提供了对基本类型及对象类型的反序列化功能

ObjectOutputStream提供了对基本类型及对象类型的序列化功能

package Object_;
import java.io.Serializable;
public class Dog implements Serializable {
    private String name;
    private int age;
    //serialVersionUID 序列化的版本号,可以提供兼容性
    private static final long serialVersionUID=1l;
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Dog() {
    }

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

对 对象的写入(序列化形式)

package Object_;

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

public class ObjectOutputStream_ {
    public static void main(String[] args) {
        String ObjPath="d:\\dog.dat";
        ObjectOutputStream oos=null;
        try {
        oos = new ObjectOutputStream(new FileOutputStream(ObjPath));
            oos.writeObject(new Dog("小花",5));
            System.out.println("写入完成(序列化形式)...");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

对对象的读取

package Object_;

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

public class ObjectInputStream_ {
    public static void main(String[] args) {
        String ObjPath="d:\\dog.dat";
        ObjectInputStream ois=null;
        try {
          ois = new ObjectInputStream(new FileInputStream(ObjPath));
            Dog o = (Dog)ois.readObject();
            System.out.println(o);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        finally {
            if (ois!=null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

注意事项

  1. 读写顺序要一致。

  2. 要求实现序列化或反序列化对象,需要实现Serializable接口。

  3. 序列化的类中建议添加SerialVersionUID,提高版本兼容性。

  4. 序列化对象时,默认将里面的所有属性都进行序列化,但除了static或transient修饰的成员。

    (1)为什么要用transient关键字?
    在持久化对象时,对于一些特殊的数据成员(如用户的密码,银行卡号等),我们不想用序列化机制来保存它。为了在一个特定对象的一个成员变量上关闭序列化,可以在这个成员变量前加上关键字transient。

    (2)transient的作用
    transient是Java语言的关键字,用来表示一个成员变量不是该对象序列化的一部分。当一个对象被序列化的时候,transient型变量的值不包括在序列化的结果中。而非transient型的变量是被包括进去的。

  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口。

  6. 序列化具有可继承性,某类实现了序列化,则它的所有子类默认实现了序列化。

6.标准输入输出流

类型 默认设备
System.in 标准输入 InputStream 键盘
System.out 标准输出 PrintStream 显示器
package Standard;

import java.io.InputStream;
import java.util.Scanner;

public class InputAndOutput {
    public static void main(String[] args) {
        /**
         * public final static InputStream in = null;
         * 1.编译类型是InputStream
         * 2.运行类型是BufferedInputStream
         * 表示的是标准输入  ->键盘
         */
        System.out.println(System.in.getClass());
        Scanner scanner = new Scanner(System.in);//例如
        /**
         *public final static PrintStream out = null;
         * 1.编译类型是PrintStream
         * 2.输出类型是PrintStream
         * 表示的是默认输出  ->显示器
         *
            */
        System.out.println(System.out.getClass());
        System.out.println("你真帅!");//例如

    }
}

7.转换流

转换流:InputStreamReader与OutputStreamWriter

作用是将字节流转换为字符流(解决字符乱码问题)

介绍:

  1. InputStreamReader是Reader的子类,可以将InputStreamReader(字节流)包装(转换)成Reader(字符流)
  2. OutputStreamWriter是Writer的子类,可以将OutputStreamWriter(字节流)包装(转换)成Writer(字符流)
  3. 当处理纯文本数据时,使用字符流效率更高,并且可以有效解决中文乱码问题,所以建议将字节流转化为字符流
  4. 可以在使用时制定编码格式(例如:utf-8,gbk,gb2312等)

未更改文件的字符编码时

[java-IO流

更改后:出现乱码
java-IO流

演示InputStreamReader_解决中文乱码问题

package transformation;

import java.io.*;

/**
 * 演示InputStreamReader_解决中文乱码问题
 */
public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        String filePath="d:\\news1.txt";
        /**
         * 1.将FileInputStream转化为InputStreamReader
         * 2.指定编码格式
         */
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
         //3.将InputStreamReader传入BufferedReader
        BufferedReader bufferedReader=new BufferedReader(isr);
        /**
         * 将2.3步结合到一起
         *   BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk"));
         */
        //4.读取
        String s=bufferedReader.readLine();
        System.out.println(s);
        //5.关闭外层流
        bufferedReader.close();


    }
}

演示使用OutputStreamWriter 使用指定编码写入文件

package transformation;

import java.io.*;

/**
 * 演示使用OutputStreamWriter 使用指定编码写入文件
 */
public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath="d:\\news.txt";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), "gbk");
        osw.write("转换流写入");
        osw.close();
        System.out.println("写入成功");
    }
}

8.打印流

PrintStream(字节流)与PrintWriter(字符流)

打印流只有输出流没有输出流

字节打印流PrintStream

package Writer_;

import java.io.IOException;
import java.io.PrintStream;

/**
 * 演示PrintWriter(字节打印流)
 */
public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream ps=System.out;
        //在默认情况下 PrintStream的输出位置是 标准输出,即显示器 控制台
        ps.print("这是标准输出!!!");
        //因为print的底层是write,所以可以直接调用write
        ps.write("这是标准输出!!!".getBytes());
        ps.close();
        //修改打印位置
        System.setOut(new PrintStream("d:\\news.txt"));
        System.out.println("你好!PrintStream");
    }
}

字符打印流PrintWriter

package Writer_;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        //修改打印位置
        PrintWriter pw=new PrintWriter(new FileWriter("d:\\news.txt"));
//        PrintWriter pw=new PrintWriter(System.out);
        pw.write("你好  java~~~~");
        pw.close();
    }
}

9.使用IO读取properties配置文件

java-IO流

例如读取连接数据库的配置文件

package properties_;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
*这是使用传统方式进行读取
*比较繁琐
*若只需要某一个值,例如ip  还需要进一步判断
*/
public class properties01 {
    public static void main(String[] args) throws IOException {
        //读取myql.properties并得到 ip user pw
        BufferedReader br = new BufferedReader(new FileReader("src\\properties_\\mysql.properties"));
        String line=null;
        while ((line=br.readLine())!=null){
            String[] spLit=line.split("=");
            System.out.println(spLit[0]+"的值是"+spLit[1]);
        }
        br.close();
    }
}

使用properties类读取配置文件

介绍:

  1. 专门读取配置文件的集合类

    配置文件的格式:

    键=值

    键=值

  2. 注意:键值对不需要有空格,值不需要用引号。默认类型是String

String getProperty(String key) 用指定的键在此属性列表中搜索属性。
String getProperty(String key ,String defaultValue) 用指定的键在属性列表中搜索属性。
void list(PrintStream out) 将属性列表输出到指定的输出流
void list(PrintWriter out) 将属性列表输出到指定的输出流。
void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
Object setProperty(String key, String value) 调用 Hashtable 的方法 put
void store(OutputStream out, String comments) 以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
void store(Writer writer, String comments) 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
package properties_;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Parameter;
import java.util.Properties;

public class properties02 {
    public static void main(String[] args) throws IOException {
        /**
         * 使用Properties读取mysql.properties文件
         */
        //1.创建Properties对象
        Properties properties=new Properties();
        //2.加载指定配置文件
        properties.load(new FileReader("src\\properties_\\mysql.properties"));
        //3.把k-v现实至打印台
        properties.list(System.out);
        //4.根据k获取v
        System.out.println("账号是"+properties.getProperty("user"));
        System.out.println("密码是"+properties.getProperty("pwd"));
    }
}

使用Properties创建修改配置文件

package properties_;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class properties03 {
    public static void main(String[] args) throws IOException {
        //Properties创建配置文件,修改配置文件内容
        //Properties的父类就是HashTable,底层就是HashTable核心方法
        Properties properties=new Properties();
        //创建
        //如果该文件没有key则为创建  有key则为修改
        properties.setProperty("user","汤姆");//注意使用FileOutputStream保存时,保存的是中文的unicode码值
        properties.setProperty("pwd","123");
        properties.setProperty("charset","utf8");
        //将k-v存储到文件中即可  中文注释在存储时也会保存的是unicode码
        properties.store(new FileOutputStream("src\\properties_\\mysql.properties"),"这个是注释");
        System.out.println("保存配置成功~");
    }
}

10.使用io进行文件夹的拷贝

package Copy;

import java.io.*;

public class copyDirectoryDemo {

    public static void main(String[] args) {
        File srcFolder = new File("C:\\Users\\xuanlong\\Desktop\\日语");
        File destFolder = new File("C:\\Users\\xuanlong\\Desktop\\日语Copy");
        fun(srcFolder, destFolder);
    }

    public static void fun(File srcFolder, File destFolder) {
        File[] fileArray = srcFolder.listFiles();
        if (!destFolder.exists()) {
            destFolder.mkdir();
        }
        for (File file : fileArray) {
            if (file.isDirectory()) {
                String folderName = file.getName();
                File newDestFolder = new File(destFolder, folderName);
                fun(file, newDestFolder);
            } else {
                String fileName = file.getName();
                File destFile = new File(destFolder, fileName);
                copy(file, destFile);
            }
        }
    }

    public static void copy(File file, File destFile) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            bos = new BufferedOutputStream(new FileOutputStream(destFile));
            byte[] bys = new byte[1024];
            int len = 0;
            while ((len = bis.read(bys)) != -1) {
                bos.write(bys, 0, len);

            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}
上一篇:关于输入提示功能实现前的基本参考


下一篇:强制执行像Facebook的代码审计