java的IO流学习笔记

1、异常处理
java 2种异常处理:
a:自己将该问题处理,然后继续运行(try catch)
try{
… //可能产生异常的地方
}catch(Exception e){
e.printStackTrace();
… //出异常后,捕获异常进行处理,jvm默认就用这种方式处理异常
return;
}finally{
… //释放资源,一定会执行,比如关闭已打开的io流。
}

        注意:
        被finally控制的语句体一定会执行,特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))
        return语句在执行之前,会检查有没有finally,如果有就将finally执行

    b:将异常抛出(throws):定义功能方法时,需要把出现的问题暴露出来让调用者去处理。
        public static void main(String[] args) throws Exception {
            Person p = new Person();
            p.setAge(-17);
            System.out.println(p.getAge());
        }

        throw的概述以及和throws的区别
            throws:用在方法声明后面,跟的是异常类名; 可以跟多个异常类名,用逗号隔开; 表示抛出异常,由该方法的调用者来处理
            throw:用在方法体内,跟的是异常对象名; 只能抛出一个异常对象名; 表示抛出异常,由方法体内的语句处理


    也可以自定义异常:
    class AgeOutOfBoundsException extends Exception {
        public AgeOutOfBoundsException() {//不带参数的构造函数
            super();
        }
        public AgeOutOfBoundsException(String message) {//带参数的构造函数
            super(message);
        }
    }

final、finally、finalize区别
    final:可以修饰类,不能被继承 ; 修饰方法,不能被重写 ; 修饰变量,只能赋值一次
    finally:是try语句中的一个语句体,不能单独使用,用来释放资源
    finalize:是一个方法,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法

如果catch里面有return语句,finally的代码会执行,但是在finally中定义的变量值不会改变,会使用return之前语句的变量值
    try {
        x = 20;
        System.out.println(1/0);
        return x;
    } catch (Exception e) {
        x = 30;
        return x;
    } finally {
        x = 40;
        //return x;                 千万不要在finally里面写返回语句
    }
    //结果会返回x=30

2、File类:文件和目录路径名的抽象表示形式
构造方法:
File(String pathname) //根据一个路径得到File对象,pathname是个绝对路径”C:\Users\user\Desktop\java\test.txt”
File(String parent, String child) //parent目录 child目录或文件名称
File(File parent, String child) //parent 是File对象(目录的File对象),child 文件名称或者目录

基本的方法:
    File file = new File("a.txt");
    file.createNewFile();              //如果没有就创建,返回true
    file.mkdir();                      //创建文件夹 如果存在这样的文件夹,就不创建了
    file.mkdirs("aa\\bb");                     //创建文件夹,如果父文件夹不存在,会帮你创建出来,创建2个层级目录

    boolean isDirectory() //判断是否是目录
    boolean isFile()      //判断是否是文件
    boolean exists()      //判断是否存在
    boolean canRead()     //判断是否可读
    boolean canWrite()    //判断是否可写
    boolean isHidden()    //判断是否隐藏
    boolean getAbsolutePath()    //获取绝对路径
    String getPath()             //获取路径
    String getName()             //获取名称
    long length()                //获取长度。字节数
    long lastModified()          //获取最后一次的修改时间,毫秒值

练习:获取d盘目录下所有的txt文件
    File dir = new File("E:\\");
    String[] arr = dir.list();                  //获取d盘下所有的文件或文件夹
    for (String string : arr) {
        if(string.endsWith(".txt")) {           //endsWith 判断是否以.txt结尾
            System.out.println(string);
    }

3、IO流:IO流用来处理设备之间的数据传输,Java用于操作流的类都在IO包中。
流按流向分为两种:输入流,输出流。
流按操作类型分为两种:
字节流 (Byte:8位0/1): 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
字节流的抽象父类:
InputStream
OutputStream
字符流 (char:具体的大小由编码表决定): 字符流只能操作纯字符数据,比较方便。
字符流的抽象父类:
Reader
Writer

字节流使用:
    a、FileInputStream基本用法:
        FileInputStream fis = new FileInputStream("a.txt");     //创建流对象
        int b;                                                  //定义变量,记录每次读到的字节,注意使用的是int类型接受
        while((b = fis.read()) != -1) {                         //将每次读到的字节赋值给b并判断是否是-1
            System.out.println(b);                              //打印每一个字节
        }
        fis.close();                                            //关闭流释放资源

        注意:
        read()方法读取的是一个字节,为什么返回是int,而不是byte?
            因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111
            那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上
            24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型。

    b、FileOutputStream基本用法:
        FileInputStream fis = new FileInputStream("a.txt");     //创建流对象
        FileOutputStream fos = new FileOutputStream("b.txt");   //创建输出流对象,关联b.txt
        int b;
        while((b = fis.read()) != -1) {
            fos.write(b);
        }
        fos.close();

    c、使用FileInputStream,FileOutputStream每次读取一个byte和写出一个byte效率太低了!!!
    解决办法可以定义一个小数组接受
        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("b.txt");
        int len;
        byte[] arr = new byte[1024 * 8];                    //自定义字节数组,默认缓冲的大小也是1024*8 byte

        while((len = fis.read(arr)) != -1) {
            //fos.write(arr);                               //如果这样写了,就会多些数据,因为读到末尾的时候不一定就是1024*8个字节
            fos.write(arr, 0, len);                         //写出字节数组写出有效个字节个数
        }
        fis.close();
        fos.close();

    d、java也考虑到了读取效率低的问题,所以封装了一个BufferedInputStream和BufferedOutputStream类来使用。
        BufferedInputStream 会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个int长度;程序再次读取时, 就不用找文件了, 直接从缓冲区中获取,直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个byte。
        BufferedOutputStream 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中,直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

        因为使用buffer操作的是内存,比直接操作硬盘效率要高很多。

        FileInputStream fis = new FileInputStream("a.mp3");             //创建文件输入流对象,关联a.mp3
        BufferedInputStream bis = new BufferedInputStream(fis);         //创建缓冲区对fis装饰
        FileOutputStream fos = new FileOutputStream("b.mp3");           //创建输出流对象,关联b.mp3
        BufferedOutputStream bos = new BufferedOutputStream(fos);       //创建缓冲区对fos装饰

        int b;                              //读取的有效长度
        while((b = bis.read()) != -1) {     //从硬盘中读取1024*8 byte
            bos.write(b);
        }

        bis.close();                        //只关装饰后的对象即可
        bos.close();

    小数组的读写和带Buffered的读取哪个更快?
        定义小数组会略胜一筹,因为读和写操作的是同一个数组,而Buffered操作的是两个数组。

    flush和close方法的区别
        用来刷新缓冲区的,刷新后可以再次写出,例如qq聊天的窗口
        用来关闭流释放资源的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出

    字节流读写中文问题:
        读中文的时候有可能会出现乱码,因为一个中文2个字符。假设文件全是中文且没有标点,字母等字符,设置arr为2的整数倍读取没有问题
        只要有标点或字母,读取的时候就可能出现读到半个中文,码表找不到的中文会用?代替。

        字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组,例如写出回车换行 
        write("\r\n".getBytes());

    e、流的标准处理异常代码1.6版本及其以前
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("a.txt");
            fos = new FileOutputStream("b.txt");
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        } finally {
            try {
                if(fis != null)
                    fis.close();
            }finally {
                if(fos != null)
                    fos.close();
            }
        }


    f、给数据加密(原理是数据异或两次后就是自己)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg"));    //可以不用分开写
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg")); //可以不用分开写

        int b;
        while((b = bis.read()) != -1) {
            bos.write(b ^ 123);
        }

        bis.close();
        bos.close();


字符流使用:字符流是可以直接读写字符的IO流
    字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出。

    a、FileReader基本用法:
        FileReader类的read()方法可以按照字符大小读取
        FileReader fr = new FileReader("a.txt");                //创建输入流对象,关联aaa.txt
        int ch;                                                 //文件是用二进制数据存储的,读取的时候会使用int类型接受,
                                                                //字符大小根据码表不同而定 GBK一个中文2个字符
        while((ch = fr.read()) != -1) {                         //将读到的字符赋值给ch
            System.out.println((char)ch);                       //将读到的字符强转后打印
        }

        fr.close();                                             //关流 


    b、FileWriter基本用法:
        FileWriter fw = new FileWriter("b.txt");
        fw.write("aaa");
        fw.close();


    c、字符流的拷贝:
        FileReader fr = new FileReader("a.txt");
        FileWriter fw = new FileWriter("b.txt");

        int ch;
        while((ch = fr.read()) != -1) {
            fw.write(ch);
        }

        fr.close();
        fw.close();
    d、什么情况下使用字符流?
        字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节;
        程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流;
        读取的时候是按照字符的大小读取的,不会出现半个中文;
        写出的时候可以直接将字符串写出,不用转换为字节数组。

        注意:
        字符流是不可以拷贝非纯文本的文件,因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替。

    e、自定义字符数组的拷贝:
        FileReader fr = new FileReader("a.txt");            //创建字符输入流,关联a.txt
        FileWriter fw = new FileWriter("b.txt");            //创建字符输出流,关联b.txt

        int len;
        char[] arr = new char[1024*8];                      //创建字符数组
        while((len = fr.read(arr)) != -1) {                 //将数据读到字符数组中
            fw.write(arr, 0, len);                          //从字符数组将数据写到文件上
        }

        fr.close();                                         //关流释放资源
        fw.close(); 

    f、带缓冲的字符流:
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));    //创建字符输入流对象,关联a.txt
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));    //创建字符输出流对象,关联b.txt

        int ch;             
        while((ch = br.read()) != -1) {     //read一次,会先将缓冲区读满,从缓冲去中一个一个的返给临时变量ch
            bw.write(ch);                   //write一次,是将数据装到字符数组,装满后再一起写出去
        }

        br.close();                         //关流
        bw.close();  

    g、readLine()和newLine()方法
        BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
        BufferedWriter的newLine()可以输出一个跨平台的换行符号"\r\n"

        例如:
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
        String line;
        while((line = br.readLine()) != null) {
            bw.write(line);
            //bw.write("\r\n");                 //只支持windows系统
            bw.newLine();                       //跨平台的
        }

        br.close();
        bw.close(); 

    h、使用指定的码表读写字符
        BufferedReader br =                                     //高效的用指定的编码表读
            new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));
        BufferedWriter bw =                                     //高效的用指定的编码表写
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));
        int ch;
        while((ch = br.read()) != -1) {
            bw.write(ch);
        }

        br.close();
        bw.close();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值