IO第二天 低级流 缓冲流BOS 对象流OOS

 1. 使用文件输入流读取文件数据   int  d = fis.read()

  文件流常用的构造器(输入输出都一样)
            FileInputStream(File file)------------------------先实例化file 传入file

            File file = new File("./fos.dat");
            FileInputStream fis = new FileInputStream(file);//读操作


            FileInputStream(String filename)--------------直接写抽象路径 少写一行

            FileInputStream  fis = new FileInputStream(",/fos.dat");

难点: InputStream上定义了读取字节的方法   输入输出流对象. read()

  •  读取1个字节,并以int形式返回。而返回的int值中只有"低八位"有数据(就是读取到的1字节的内容)。
  •  如果返回的int值为整数-1,则表达流读取到了末尾(不可再通过这个流读取到任何数据了)。

        //读取当前目录下的fos.dat文件中的字节数据
//        File file = new File("./fos.dat");
//        FileInputStream fis = new FileInputStream(file);//读操作
//        FileOutputStream fos = new FileOutputStream(file);//写操作
        FileInputStream fis = new FileInputStream("./fos.dat");
        /*
            
            fos.dat文件内容:
            00000001 00000010

            第一次调用:int d = fis.read();//读取文件的第一个字节
            fos.dat文件内容:
            00000001 00000010
            ^^^^^^^^
            读取该字节
            返回值d的2进制样子:00000000 00000000 00000000 00000001
                            |-------自动补充24个0------| ^^^^^^^^
                                                       本次读取的
         */
        int d = fis.read();
        System.out.println(d); //输出1

        /*
            第二次调用:d = fis.read();//读取文件的第二个字节
            fos.dat文件内容:
            00000001 00000010
                     ^^^^^^^^
                     读取该字节

            返回值d的2进制样子:00000000 00000000 00000000 00000010
                            |-------自动补充24个0------| ^^^^^^^^
                                                       本次读取的
         */
        d = fis.read();
        System.out.println(d);//输出2

        /*
            第三次调用:d = fis.read();//读取文件的第三个字节
            fos.dat文件内容:
            00000001 00000010 没有数据了
                              ^^^^^^^^
                              文件末尾了

            返回值d的2进制样子:11111111 11111111 11111111 11111111
                            |-----------自动补充32个1-----------|


         */
        d = fis.read();
        System.out.println(d);//输出-1

        fis.close();
    }
}

2.复制文件(输入再输出)

先声明int d----while循环判断d=fis.read不等于-1------fos.write

读取一个字节并输出


    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("./10904.jpg");
        FileOutputStream fos=new FileOutputStream("./image.jpg");
        int d;
      
        long start = System.currentTimeMillis();//获取当前系统时间的毫秒值
        //一开始嫌麻烦 d初始化并赋值了 不可以! 每一遍赋值不能为-1
        while((d = fis.read())!=-1){//每次循环先读取1个字节,判断是否读取到末尾
            fos.write(d);//没有读取到末尾就将读取的字节写入复制的文件中
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时:"+(end-start)+"ms");
        fis.close();
        fos.close();
   

前后时间一减 知道花了多长时间复制文件  System.currentTimeMillis();

package io;

public class Demo {
    public static void main(String[] args) {
        //自1970-01-01 00:00:00到当前系统时间所经过的毫秒
        // 用long值 因为int才21亿不够用
        long now = System.currentTimeMillis();
        System.out.println(now);

        now = now/1000/60/60/24/365;
        System.out.println(now);//52年


        long max = Long.MAX_VALUE;
        max = max/1000/60/60/24/365;
        System.out.println("公元:"+(max+1970));//公元292473178

    }
}

块读写操作

提高每次读写的数据量,减少读写次数可以提高读写效率 时间消耗在来回跑的路上
一组字节一次性读写操作称为:块读写操作

  InputStream字节输入流的超类上规定了块读操作:
            byte[] data = new byte[3];

       int read(byte[] data)

            一次性读取给定的字节数组data总长度的字节量并装入到该数组中
            返回值为实际读取到的字节数。如果返回值为整数-1则表达流读取到末尾了

一个bit可以存一个8位2进制   

01111111 127

第一位当成符号位去用了 0为正 1为负

块读演示


            原文件内容(5个字节):
            11001100 10101010 11110000 00001111 01010101

            int len=0;
            //二进制形式data:{00000000,00000000,00000000}
            byte[] data = new byte[3];


            第一次调用:
            len = fis.read(data);//data长度为3,因此一次性要读取3个字节
            原文件内容:
            11001100 10101010 11110000 00001111 01010101
            ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
               本次读取到的3个字节内容

            data:{11001100,0101010,11110000}
                 数组的三个字节为本次实际读取内容
            len=3;//len为整数3,表达本次实际读取到了3个字节


            第二次调用:
            len = fis.read(data);//data长度为3,因此一次性要读取3个字节
            原文件内容:
            11001100 10101010 11110000 00001111 01010101 没有数据了
                                       ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
                                       本次实际读取到的2字节

            data:{00001111,01010101,11110000}
                  ^^^^^^^^ ^^^^^^^^ |-旧数据-|
                  |-本次读取的新数据-|
            len=2;//len为整数2,表达本次实际读取到了2个字节


            第三次调用:
            len = fis.read(data);//data长度为3,因此一次性要读取3个字节
            原文件内容:
            11001100 10101010 11110000 00001111 01010101 没有数据了
                                                         ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
                                                         本次没有读取到任何数据

            data:{00001111,01010101,11110000}
                  |---------旧数据----------|

            len=-1;//len为整数-1,表达已经是流的末尾了,本次没有读取任何数据。

       8位2进制       1个字节
            00000000      1byte

            1024byte      1kb
            1024kb        1mb
            1024mb        1gb
            1024gb        1tb
            1024tb        1pb

       块写操作

     OutputStream字节输出流的超类上,定义了块写操作
            void write(byte[] data)
            一次性将给定的字节数组中所有字节写出

            void write(byte[] data,int offset,int len)
            一次性将给定的字节数组data中从下标offset处开始的连续len个字节
            一次性写出
      


public class CopyDemo2 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("./wnwb.exe");
        FileOutputStream fos = new FileOutputStream("./wnwb_cp.exe");
       
        int len;
     
        byte[] data = new byte[1024*10];//10kb 计算表达式比10240更好理解
        long start = System.currentTimeMillis();
        //传入字节数组data
        while((len = fis.read(data))!=-1){
            fos.write(data,0,len);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时:"+(end-start)+"ms");
        fis.close();
        fos.close();

    }
}

复制后的文件比源文件大    len表示文件多少可用字节

3.写出文本数据   getBytes((StandardCharsets.UTF_8) 字符串转字节数组


/**
 * 使用输出流写出文本数据
 */
public class eWriteStringDemo {
    public static void main(String[] args) throws IOException {
        //向文件中写入文本数据
        FileOutputStream fos = new FileOutputStream("demo.txt");

        String line = "和我在成都的街头走一走,哦哦哦哦。";
        /*
            UTF编码:unicode传输编码
            UTF里面包含了全世界所有在用的流行文字
            英文:1个字符占1个字节,维持ASC部分内容
            中文:1个字符占3个字节
         */
        byte[] data = line.getBytes(StandardCharsets.UTF_8);
        fos.write(data);

        line = "直到所有的灯都熄灭了也不停留。";
        data = line.getBytes(StandardCharsets.UTF_8);
        fos.write(data);

        System.out.println("写出完毕!");
        fos.close();
    }
}

package io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 实现一个简易记事本工具:
 * 程序启动后将用户在控制台输入的每一行字符串都写入到文件note.txt中。
 * 如果用户单独输入"exit"则程序退出。
 *
 * 你好
 * 嘿嘿
 * 呵呵
 * exit
 *
 * 文件:
 * 你好嘿嘿呵呵
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("note.txt");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请开始输入内容,单独输入exit退出。");
        while(true){
            String line = scanner.nextLine();//1获取输入的一行字符串
            if("exit".equalsIgnoreCase(line)){//2如果为exit,则退出
                break;
            }
            //3将内容写入文件
            byte[] data = line.getBytes(StandardCharsets.UTF_8);
            fos.write(data);
        }
        fos.close();
        System.out.println("再见!");
    }
}

4.fos覆盖与追加

5.阅读文本数据

public class eReadStringDemo {
    public static void main(String[] args) throws IOException {
        //将当前源代码读取出来并输出到控制台上
        File file = new File("./src/main/java/io/ReadStringDemo.java");
        FileInputStream fis = new FileInputStream(file);
        //创建与文件等长的字节数组
        byte[] data = new byte[(int)file.length()];

        //核心的步骤:先读取对应的字节,再将字节还原为字符串
        fis.read(data);//一次性将文件所有字节读入数组
        String line = new String(data, StandardCharsets.UTF_8);

        System.out.println(line);//将转换后的字符串输出到控制台
        fis.close();
    }
}

6.高级流

public class eReadStringDemo {
    public static void main(String[] args) throws IOException {
        //将当前源代码读取出来并输出到控制台上
        File file = new File("./src/main/java/io/ReadStringDemo.java");
        FileInputStream fis = new FileInputStream(file);
        //创建与文件等长的字节数组
        byte[] data = new byte[(int)file.length()];

        //核心的步骤:先读取对应的字节,再将字节还原为字符串
        fis.read(data);//一次性将文件所有字节读入数组
        String line = new String(data, StandardCharsets.UTF_8);

        System.out.println(line);//将转换后的字符串输出到控制台
        fis.close();
    }
}

 缓冲区 flush

 

/**
 * 缓冲流写出时的缓冲区问题
 */
public class fFlushDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("bos.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        String line = "和我在成都的街头走一走,哦哦哦哦~";
        bos.write(line.getBytes(StandardCharsets.UTF_8));
        /*
            缓冲输出流的flush方法会强制将缓冲流中已经缓冲的数据一次性写出

            flush方法是在接口:Flushable中定义的
            而字节输出流的超类OutputStream实现了该接口,这以为这所有字节输出流
            都具有该方法。
            但是只有缓冲流真正实现了flush应有的功能。其他的高级流flush方法的实现
            都是调用其连接的流的flush方法,将该动作传递下去。
         */
//        bos.flush();//flush:冲水

        System.out.println("写出完毕!");
        //缓冲输出流的close方法中会自动调用一次flush确保所有数据关闭前写出
        bos.close();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值