JAVA字节流的两个重要子类FileOutputStream、FileInputStream

字节流,字符集,字符流

Snipaste_2024-02-05_14-18-35.png
因为它们都是抽象类,所以要学习它们的子类


字节流的结构:Snipaste_2024-02-05_14-19-49.png

FileOutputStream

操作本地文件的字节输出流,可以把程序中的数据写入本地文件。

书写步骤:

  1. 创建字节输出流对象
  2. 写数据
  3. 释放资源

演示:

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

        //1.创建字节输出流对象
        /*
        细节:
        1.参数是字符串路径或是File对象都可以
        2.如果文件不存在,会创建一个新的文件,但要保证父级路径一定存在
        3.若文件已存在,构造方法,**会清空文件
         */
        FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");
        //2.写数据
        /*
        细节:write方法的参数是整数,但是实际上写到本地文件中的是整数在AScII上对应的字符
        如执意要写当前录入的数字,可以根据Ascii表的对应关系表示:48-0
        如:要写数字65
        fos.write(54);//6
        fos.write(53);//5
         */
        fos.write(97)//a
        fos.write(98)//b
        //3.释放资源:目的是解除资源的占用
        fos.close();
    }
}

image.pngimage.png

  1. 创建字节输出流 就好比程序 和 文件a.txt建立起一条道路
  2. 写数据 ** 就好比在这条路上运送货物,程序是始发地,文件是目的地**
  3. 释放资源 就是把这条路关闭

FileOutputStream写数据的三种方式:

image.png
第一种已经演示过了:
就演示第二种和第三种:

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

    //1创建字节输出流对象
    FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");
    //2写入数据
        //字符串表示要写入的数据
    String s = "HelloWorld";
        //调用getBytes方法,得到字节数组
    byte[] bytes = s.getBytes();
        //放入字节数组
    fos.write(bytes);
    //3释放资源
    fos.close();
    }
}

public class Test3 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");
        byte[] bytes = {97, 98, 99};
        fos.write(bytes);
        fos.close();
    }
}

image.pngimage.png

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

    //1创建字节输出流对象
    FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");
    //2写入数据
        //字符串表示要写入的数据
    String s = "HelloWorld";
        //调用getBytes方法,得到字节数组
    byte[] bytes = s.getBytes();
        //放入字节数组
    fos.write(bytes,3,3);//参数2表示开始索引,参数3表示长度
    //3释放资源
    fos.close();
        
    }
}

image.png


换行和续写

在上面的演示中有没有发现一个问题?

  1. 连续两次wirte写入的数据没有换行
    1. image.pngimage.png
  2. 每一次重启程序,之前写入的数据不能保留

解决:
换行:在连续write间再写一个换行符即可
image.png
换行演示:

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

        //创建字节流输出对象
        FileOutputStream fos=new FileOutputStream("..\\ioDemo\\a.txt");
        //写入第一个数据
        String str="JAVA";
        byte[] bytes = str.getBytes();
        fos.write(bytes);

        //换行回车
        String str2="\r\n";//表示回车、换行
        byte[] bytes1 = str2.getBytes();
        fos.write(bytes1);

        //写入第二个数据
        String str3="HelloWorld";
        byte[] bytes2 = str3.getBytes();
        fos.write(bytes2);
        fos.close();
    }
}

image.png

续写演示:
创建字节流对象时,在第二个参数打开续写开关即可,true
这样就不会清空之前的内容了,

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

        //创建字节流输出对象
        FileOutputStream fos=new FileOutputStream("..\\ioDemo\\a.txt",true);

        //换行回车
        String str2="\r\n";
        byte[] bytes1 = str2.getBytes();
        fos.write(bytes1);


        //写入第三个数据
        String str4="666";
        byte[] bytes3 = str4.getBytes();
        fos.write(bytes3);

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

image.png在之前的基础上换行,添加666


FileInputStream

操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来。

书写步骤:

  1. 创建字节输入流对象
    1. 若要读取的文件不存在,就直接报错
  2. 读数据
    1. 无参的read方法一次读一个字节,读出来的是数据在ASCII上对应的数字
    2. 读到文件末尾了,read方法返回-1。
  3. 释放资源
    1. 每次使用完流必须要释放资源。

读取代码演示:

读取就像一个指针,读取一个,指针向后移动一格

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


        //创建
        FileInputStream fis=new FileInputStream("..\\ioDemo\\a.txt");
        //读取数据,获取的是单个字符对应的ascii码,当然可以强转为字符
        int read1 = fis.read();
        System.out.println(read1);//97

        int read2 = fis.read();
        System.out.println((char) read2);// b

        int read3 = fis.read();
        System.out.println((char) read3);// c

        int read4 = fis.read();
        System.out.println(read4);//100

        int read5 = fis.read();
        System.out.println(read5);//101

        int read6 = fis.read();
        System.out.println(read6);//-1
        //释放资源
        fis.close();
    }
}

image.png


上面读数据的方法太慢了,当数据很大时,不断手动调用read方法肯定不合理

使用循环读取文件:

public class t02 {
    public static void main(String[] args) throws IOException {
        /**
         *
         * 字节输入流的循环读取
         */
        
        //1.创建对象
        FileInputStream fis = new FileInputStream("..\\ioDemo\\a.txt");
        //2.循环读数据
        int len;//定义变量接收
        //读取到数据就进入
        while((len=fis.read())!=-1){
            System.out.print((char) len);
        }
        fis.close();

        //错误演示:错在多次调用了fis.read方法,是的指针发生了偏移
        /*
        while ((fis.read() != -1)) {
            int read = fis.read();
            System.out.println(read);
        }
        fis.close();
        */

    }
}

image.png

控制台:
abcde


在上面我们只是读取了数据,
现在我们来试试,不但要读取数据,还要将数据输出到另一个位置,即__数据的拷贝
如图:
Snipaste_2024-02-05_19-00-14.png
那么我们现在就用无参的read方法来实现mp4数据的拷贝:

public class t3 {
    public static void main(String[] args) throws IOException {
        long l = System.currentTimeMillis();//开始时间
        //1.字节流输入对象--为了读取
        FileInputStream fis=new FileInputStream("E:\\aaa-FIle学习测试\\ccc\\movie.mp4");
        //2.字节流输出对象--为了写入
        FileOutputStream fos=new FileOutputStream("..\\ioDemo\\Copy.mp4");
        
        //**读取
        int b;//定义变量接b收bb
        //读取到数据就进入
        while((b=fis.read())!=-1){
            //**写入
            fos.write(b);//读出来的len是对应的ascii,但write方法会自动将数字转为对应字符
        }

        fos.close();
        fis.close();

        long l1 = System.currentTimeMillis();//结束时间

        long l2 = l1 - l;
        System.out.println("花费的毫秒值:"+l2);//花费时间
    }
}

控制台:
花费的毫秒值:12048

image.png
虽然说拷贝成功,但可以发现拷贝速度是很慢的。
这是因为无参的read方法实际上一次只能读取一个字节的数据。Snipaste_2024-02-05_20-50-52.png


现在我们就来学read的重载方法
image.png
形参是一个字节数组,好比是一个容器
这个字节数组的长度,就规定了每一次调用read方法读取到的数据的字节大小,(即一次读一个字节数组的数据,每次读取会尽可能把数组装满。)每次读取到的元素放入该字节数组
一般将字节数组的长度定义为1024的整数倍,如102410245(五兆)

在改写拷贝代码前,我们先熟悉这个重载方法:

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

        
        //创建字节流输入对象
        FileInputStream fis=new FileInputStream("..\\ioDemo\\a.txt");
        //创建字节数组
        byte[]arr=new byte[2];//表示一次只读取两个字节,读取到的元素放入该数组

        //*开始读取
        int num1 = fis.read(arr);//返回值表示读取的字节个数
        System.out.println(num1);
        //***打印当前的字节数组
        String str1=new String(arr);
        System.out.println(str1);


        //读取
        int num2 = fis.read(arr);//返回值表示读取的字节个数
        System.out.println(num2);
        //***打印字节数组
        String str2=new String(arr);
        System.out.println(str2);



        //读取
        int num3 = fis.read(arr);//返回值表示读取的字节个数
        System.out.println(num3);//***此时只读取到最后一个元素e
        //***打印字节数组
        String str3=new String(arr);
        System.out.println(str3);//只读取到最后一个元素e,所以只能将cd中的c覆盖,所以打印ed

        //若要打印每次获取到的元素可以这样做:String str=new String (arr ,0 , num)

    }
}

image.png

2-------------------第一次获取了 两字节
ab------------------字节数组内的元素
2------------------第二次获取了 两字节
cd------------------字节数组内的元素
1------------------第二次获取了 一字节
ed------------------因为只读取到最后一个元素e,所以只能将之前cd的c覆盖,所以打印ed

//若要打印每次获取到的元素可以这样做:String str=new String (arr ,0 , num)
0表示开始索引,num表示当前读取到的字节个数

//一次读取一个字节数组


        FileInputStream fis=new FileInputStream("..\\ioDemo\\a.txt");



        byte[]arr=new byte[2];//表示一次只读取两个字节,读取到的元素放入该数组

        //读取
        int num1 = fis.read(arr);//返回值表示读取的字节个数
        System.out.println(num1);
        //***打印字节数组
        String str1=new String(arr,0,num1);
        System.out.println(str1);


        //读取
        int num2 = fis.read(arr);//返回值表示读取的字节个数
        System.out.println(num2);
        //***打印字节数组
        String str2=new String(arr,0,num2);
        System.out.println(str2);



        //读取
        int num3 = fis.read(arr);//返回值表示读取的字节个数
        System.out.println(num3);//***此时只读取到最后一个元素e
        //***打印字节数组
        String str3=new String(arr,0,num3);
        System.out.println(str3);

2
ab
2
cd
1
e


正式改进拷贝代码:

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

        /**
         *
         * 文件拷贝改写
         */

        long start = System.currentTimeMillis();//开始时间
        //创建字节流输入,输出对象
        FileInputStream fis=new FileInputStream("E:\\aaa-FIle学习测试\\ccc\\movie.mp4");
        FileOutputStream fos=new FileOutputStream("..\\ioDemo\\Copy.mp4");



        byte[]bytes=new byte[1024*1024*5];//一次读取五兆,即表示写入速度,又表示存储位置
        int len;//每次的写入字节大小
        while((len=fis.read(bytes))!=-1){
            fos.write(bytes,0,len);//再将每次写入的数据,输出到目的地
        }

        //先调用者,后关闭
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();//结束时间
        System.out.println((end-start));//花费时间

    }
}



225

速度明显变快了。
image.png

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

成果、

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

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

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

打赏作者

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

抵扣说明:

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

余额充值