IO流学习--1

IO流:存储和读取数据的解决方案。用于读写文件中的数据(可以读写文件,或数据中的网络)

output:写出数据,将程序保存到本地文件中。程序--->文件

input:读取数据,本地文件加载到程序中。文件--->程序


IO流中是以程序为参照物在读写,是程序在读取文件中的数据,是程序在往文件中写出数据,或者说是内存也是可以的,因为程序运行在内存中的。

1、IO流的分类

按照流的方向分为:输入(读取)流和输出(写出)流。

按照操作文件类型分:字节流和字符流。


字节流:可以操作所有类型的文件。

字符流:只能操作纯文本文件。纯文本文件是Windows自带的记事本打开能读懂,如txt、md、xml、lrc文件,而word、excel不是纯文本文件。

2、IO流体系

字节流:InputStream字节输入流、OutputStream字节输出流。

字符流:Reader字符输入流、Writer字符输出流。


 InputStream、OutputStream、Reader、Writer都是抽象类,不能直接创建他们的对象。要看他们的子类。

3、FileOutputStream

FileOutputStream  操作本地文件的字节输出流,可以把程序中的数据写到本地文件中
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("D:\\JavaTest\\myio\\myio\\a.txt");
        //2.写出数据
        fos.write(97);
        //3.释放资源
        fos.close();

字节输出流的细节:
1.创建字节输出流对象
        参数是字符串表示的路径或者是File对象都是可以的
        如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
        如果文件已经存在,则会清空文件
2.写数据
        write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
3.释放资源
        每次使用完流之后都要释放资源

FileOutputStream原理:

FileOutputStream fos = new FileOutputStream("D:\\JavaTest\\myio\\myio\\a.txt");
根据书写的路径让文件跟程序之间产生一个数据传送的通道,
fos.write(97);通过write方法写出数据,相当于在通道中进行数据传输
fos.close();关闭这个通道

FileOutputStream写数据的三种方式:

public class ByteStreamDemo3 {
    public static void main(String[] args) throws IOException {
        /*
           void write(int b)                       一次写一个字节数据
           void write(byte[] b)                    一次写一个字节数组数据
           void write(byte[] b, int off, int len)  一次写一个字节数组的部分数据
           参数一:
                数组
           参数二:
                起始索引
           参数三:
                个数
        */

        //1.创建对象
        FileOutputStream fos = new FileOutputStream("myio\\a.txt");
        //2.写出数据
       /* //方式一:一次写一个字节数据
        fos.write(97); // a   
        fos.write(98); // b*/
        
        byte[] bytes = {97, 98, 99, 100, 101};
       /* //方式二:一次写一个字节数组数据
        fos.write(bytes);*/

        //方式三:一次写一个字节数组的部分数据
        fos.write(bytes,1,2);// b c
        //3.释放资源
        fos.close();
    }
}

FileOutputStream写出数据的两个小问题:

public class ByteStreamDemo4 {
    public static void main(String[] args) throws IOException {
        /*
            1、换行写:
                再次写出一个换行符就可以了
                windows: \r\n  回车换行,回车是把光标移到这行前面,换行是把光标移到下一行
                Linux:    \n
                Mac:      \r
            细节:
                在windows操作系统当中,java对回车换行进行了优化。
                虽然完整的是\r\n,但是我们写其中一个\r或者\n,
                java也可以实现换行,因为java在底层会补全。
            建议:
                不要省略,还是写全了。

            2、续写:
                如果想要续写,打开续写开关即可
                开关位置:创建对象的第二个参数
                默认false:表示关闭续写,此时创建对象会清空文件
                手动传递true:表示打开续写,此时创建对象不会清空文件

        */


        //1.创建对象
        FileOutputStream fos = new FileOutputStream("myio\\a.txt",true);
        //2.写出数据
        String str = "kankelaoyezuishuai";
        byte[] bytes1 = str.getBytes();
        fos.write(bytes1);

        //再次写出一个换行符就可以了
        String wrap = "\r\n";
        byte[] bytes2 = wrap.getBytes();
        fos.write(bytes2);

        String str2 = "666";
        byte[] bytes3 = str2.getBytes();
        fos.write(bytes3);

        //3.释放资源
        fos.close();
    }
}

 

4、FileInputStream

FileInputStream 操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来
public class ByteStreamDemo1 {
    public static void main(String[] args) throws IOException {
        /*
         * 演示:字节输入流FileInputStream
         * 实现需求:读取文件中的数据。(暂时不写中文)
         *
         * 实现步骤:
         *       创建对象
         *       读取数据
         *       释放资源
         * */

        //1.创建对象
        FileInputStream fis = new FileInputStream("myio\\a.txt");//文本a中是:a b c d e
        //2.读取数据
        int b1 = fis.read();
        System.out.println((char)b1);//a
        int b2 = fis.read();
        System.out.println((char)b2);//b
        int b3 = fis.read();
        System.out.println((char)b3);//c
        int b4 = fis.read();
        System.out.println((char)b4);//d
        int b5 = fis.read();
        System.out.println((char)b5);//e
        int b6 = fis.read();
        System.out.println(b6);//-1   读不到数据返回-1
        //3.释放资源
        fis.close();
    }
}

字节输入流的细节:
1.创建字节输入流对象
        细节1:如果文件不存在,就直接报错。Java为什么会这么设计呢?
        
        输出流:不存在,创建     把数据写到文件当中
        输入流:不存在,而是报错呢?
        因为创建出来的文件是没有数据的,没有任何意义。所以Java就没有设计这种无意义的逻辑,文件不存在直接报错。

        程序中最重要的是:数据。

        
2.写数据
        细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字
        细节2:读到文件末尾了,read方法返回-1。如果读取的是-1, -  1  分开读
3.释放资源
        细节:每次使用完流之后都要释放资源

FileInputStream循环读取:

public class ByteStreamDemo3 {
    public static void main(String[] args) throws IOException {
         /*
             字节输入流循环读取
         */

       //1.创建对象
        FileInputStream fis = new FileInputStream("myio\\a.txt");
        //2.循环读取
        int b;
        while ((b = fis.read()) != -1) {
            System.out.println((char) b);
        }
        //3.释放资源
        fis.close();
        
        /*以下错误代码:
        //read :表示读取数据,而且是读取一个数据就移动一次指针
        
        FileInputStream fis = new FileInputStream("myio\\a.txt");
        //2.循环读取
        while ((fis.read()) != -1) {
            System.out.println(fis.read());//98  100  -1
        }
        //3.释放资源
        fis.close();*/
    }
}

5、文件拷贝

一次读取一个字节  速度慢

public class ByteStreamDemo4 {
    public static void main(String[] args) throws IOException {
        /*
        *   练习:
        *       文件拷贝
        *       把D:\itheima\movie.mp4拷贝到当前模块下。
        *   练习:
        *       要求统计一下拷贝时间,单位毫秒
        * */

        long start = System.currentTimeMillis();

        //1.创建对象
        FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
        //2.拷贝
        //核心思想:边读边写
        int b;
        while((b = fis.read()) != -1){
            fos.write(b);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();

        System.out.println(end - start);

    }
}

 


 一次读取一个字节数组的数据,每次读取会尽可能把数组装满

public class ByteStreamDemo5 {
    public static void main(String[] args) throws IOException {
      /*
          public int read(byte[] buffer)      一次读一个字节数组数据
      */
        
        //1.创建对象
        FileInputStream fis = new FileInputStream("myio\\a.txt");//a:abcde
        //2.读取数据
        byte[] bytes = new byte[2];
        //一次读取多个字节数据,具体读多少,跟数组的长度有关
        //返回值:本次读取到了多少个字节数据
        int len1 = fis.read(bytes);
        System.out.println(len1);//2
        String str1 = new String(bytes,0,len1);
        System.out.println(str1);//ab
        
        int len2 = fis.read(bytes);
        System.out.println(len2);//2
        String str2 = new String(bytes,0,len2);//内存中会覆盖之前读取的ab
        System.out.println(str2);//cd

        int len3 = fis.read(bytes);
        System.out.println(len3);// 1
        String str3 = new String(bytes,0,len3);
        System.out.println(str3);// e
        
        //3.释放资源
        fis.close();
    }
}

 练习1:优化之前的代码

public class ByteStreamDemo6 {
    public static void main(String[] args) throws IOException {

      /* 练习:
           文件拷贝
           把D:\itheima\movie.mp4 (16.8 MB) 拷贝到当前模块下。*/

        long start = System.currentTimeMillis();

        //1.创建对象
        FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");//拷贝到
        //2.拷贝
        int len;
        byte[] bytes = new byte[1024 * 1024 * 5];//5MB大小的数组
        while((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);//读取多少写多少
        }
        //3.释放资源
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();

        System.out.println(end - start);
    }
}

 6、不同JDK版本的捕获异常处理

基本做法: 手动释放资源

try {
    可能出现异常的代码;
} catch (异常类名 变量名) {
    异常的处理代码;
} finally {
   执行所有资源后释放操作;
}

注意:finally里面的代码一定被执行,除非虚拟机停止。

public class ByteStreamDemo7 {
    public static void main(String[] args) {
        //利用try...catch...finally捕获拷贝文件中代码出现的异常
        
        //1.创建对象
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\itheima\\movie.mp4");
            fos = new FileOutputStream("myio\\copy.mp4");
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while((len = fis.read(bytes)) != -1){
                fos.write(bytes,0,len);
            }
        } catch (IOException e) {
            //e.printStackTrace();
        } finally {
            //3.释放资源
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 接口:AutoCloseable    特定情况下,可以自动释放资源。

 JDK7方案:仅了解    资源用完最终自动释放

try (创建流对象1;创建流对象2) {
   可能出现异常的代码;
} catch (异常类名 变量名) {
   异常的处理代码;
}

注意:只有实现了AutoCloseable 接口的类,才能在小括号中创建流对象。

public class ByteStreamDemo8 {
    public static void main(String[] args) {
        /*JDK7:IO流中捕获异常的写法*/

        //try后面的小括号中写创建对象的代码
        //注意:只有实现了AutoCloseable接口的类,才能在小括号中创建对象。
        try (FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
             FileOutputStream fos = new FileOutputStream("myio\\copy.mp4")) {
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 JDK9方案:仅了解    资源用完最终自动释放

创建流对象1;
创建流对象2;

try (流1;流2) {
    可能出现异常的代码;
} catch (异常类名 变量名) {
    异常的处理代码;
}
public class ByteStreamDemo9 {
    public static void main(String[] args) throws FileNotFoundException {//异常抛出处理
        //JDK9:IO流中捕获异常的写法
        
        FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");

        try (fis;fos) {
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梧桐小玉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值