• 97.Java中IO流_字节流_InputStream


    1.InputStream

    案例:读取"c:/a.txt"文件中的所有内容并在控制台显示出来。

    注意:事先准备一个a.txt并放到c:/下,不要保存中文。

          a, 使用read()方法实现。

          b, 使用int read(byte[] b)方法实现。

    写代码读取"c:/a.txt"文件中的所有的内容并在控制台显示出来

    实现:

    查看api文档(自己一定要动手)

    InputStream 有read方法,一次读取一个字节,OutputStream的write方法一次写一个int。发现这两个类都是抽象类。意味着不能创建对象,那么需要找到具体的子类来使用。

    通过查看api文档,找到了FileInputStream类,该类正是我们体验Io流的一个输入流。

    实现;显示指定文件内容。
    明确使用流,使用哪一类流?使用输入流,FileInputStream
    第一步:
    1:打开流(即创建流)
    第二步:
    2:通过流读取内容
    第三步:
    3:用完后,关闭流资源

    显然流是Java中的一类对象,要打开流其实就是创建具体流的对象,由于是读取硬盘上的文件,应该使用输入流。所以找到了InputStream类,但是InputStream是抽象类,需要使用它的具体实现类来创建对象就是FileInputStream。通过new 调用FileInputStream 的构造方法来创建对象。发现FileInputStream的构造方法需要指定文件的来源。查看构造方法,可以接受字符串也可以接受File对象。我们通过构建File对象指定文件路径。

    使用流就像使用水管一样,要打开就要关闭。所以打开流和关闭流的动作是比不可少的。如何关闭流?使用close方法即可,当完成流的读写时,应该通过调用close方法来关闭它,这个方法会释放掉十分有限的操作系统资源.如果一个应用程序打开了过多的流而没有关闭它们,那么系统资源将被耗尽.

       如何通过流读取内容?

    查找api文档通过read方法,查看该方法,发现有返回值,并且是int类型的,该方法一次读取一个字节(byte)

    1.1.   输入流读取方式1:

    read方法()

    一次读取一个字节,读到文件末尾返回-1.

    仔细查看api文档发现read方法如果读到文件的末尾会返回-1。那么就可以通过read方法的返回值是否是-1来控制我们的循环读取。

    /**
         * 根据read方法返回值的特性,如果独到文件的末尾返回-1,如果不为-1就继续向下读。
         * */
    private static void showContent(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            int len = fis.read();
            while (len != -1) {
                System.out.print((char)len);
                len = fis.read();
    
            }
            // 使用完关闭流
            fis.close();
        }

    我们习惯这样写:

    /**
         * 根据read方法返回值的特性,如果独到文件的末尾返回-1,如果不为-1就继续向下读。
         * */
        private static void showContent(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            int len;
            while ((len = fis.read()) != -1) {
                System.out.print((char) len);
            }
            // 使用完关闭流
            fis.close();
        }

    1.2.   输入流读取方式2:

    使用read(byte[] b) 方法。使用缓冲区(关键是缓冲区大小的确定)

    使用read方法的时候,流需要读一次就处理一次,可以将读到的数据装入到字节数组中,一次性的操作数组,可以提高效率。

    问题1:缓冲区大小

    那么字节数组如何定义?定义多大?

    可以尝试初始化长度为5的byte数组。通过read方法,往byte数组中存内容

    那么该read方法返回的是往数组中存了多少字节。

    /**
         * 使用字节数组存储读到的数据
         * */
        private static void showContent2(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            // 通过流读取内容
            byte[] byt = new byte[5];
            int len = fis.read(byt);
            for (int i = 0; i < byt.length; i++) {
                System.out.print((char) byt[i]);
            }
    
            // 使用完关闭流
            fis.close();
        }

    问题1: 缓冲区太小:

       数据读取不完.

    测试发现问题,由于数组太小,只装了5个字节。而文本的字节大于数组的长度。那么很显然可以将数组的长度定义大一些。例如1024个。

    /**
         * 使用字节数组存储读到的数据
         * */
        private static void showContent2(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            // 通过流读取内容
            byte[] byt = new byte[1024];
            int len = fis.read(byt);
            for (int i = 0; i < byt.length; i++) {
                System.out.print(byt[i]);
            }
            
            // 使用完关闭流
            fis.close();
        }

    问题三:缓冲区有默认值.

    测试,打印的效果打印出了很多0,因为数组数组有默认初始化值,所以,我们将数组的数据全部都遍历和出来.现在需要的是取出数组中的部分数据.需要将循环条件修改仔细查看api文档。发现该方法read(byte[] b)返回的是往数组中存入了多少个字节。就是数组实际存储的数据个数。

    /**
         * 使用字节数组存储读到的数据
         * */
        private static void showContent2(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            // 通过流读取内容
            byte[] byt = new byte[1024];
            int len = fis.read(byt);
            for (int i = 0; i <len; i++) {
                System.out.print(byt[i]);
        }
            
            // 使用完关闭流
            fis.close();
        }

    总结:

    问题一:为什么打印的不是字母而是数字,

           是字母对应的码值。

           如何显示字符,强转为char即可

    问题二:注意:回车和换行的问题。

           windows的换车和换行是" " 对应码表是13和10 。

    1.3.  输入流读取方式3:

    使用read(byte[] b,int off,int len)

    查看api文档,

    b显然是一个byte类型数组,当做容器来使用

    off,是指定从数组的什么位置开始存字节

    len,希望读多少个

    其实就是把数组的一部分当做流的容器来使用。告诉容器,从什么地方开始装要装多少。

    /**
         * 把数组的一部分当做流的容器来使用
         * read(byte[] b,int off,int len)
         */
        private static void showContent3(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            // 通过流读取内容
            byte[] byt = new byte[1024];
            // 从什么地方开始存读到的数据
            int start = 5;
            
            // 希望最多读多少个(如果是流的末尾,流中没有足够数据)
            int maxLen = 6;
    
            // 实际存放了多少个
            int len = fis.read(byt, start, maxLen);
    
            for (int i = start; i < start + maxLen; i++) {
                System.out.print((char) byt[i]);
            }
    
            // 使用完关闭流
            fis.close();
        }

    需求2:测试skip方法

    通过Io流,读取"c:/a.txt"文件中的第9个字节到最后所有的内容并在控制台显示出来。

    分析:其实就是要跳过文件中的一部分字节,需要查找API文档。可以使用skip方法skip(long n),参数跟的是要跳过的字节数。

    我们要从第9个开始读,那么要跳过前8个即可。

    /**
         * skip方法
         * 
         * */
        private static void showContent4(String path) throws IOException {
            // 打开流
            FileInputStream fis = new FileInputStream(path);
    
            // 通过流读取内容
            byte[] byt = new byte[1024];
            fis.skip(8);
            int len = fis.read(byt);
            System.out.println(len);
            System.out.println("**********");
            for (int i = 0; i < len; i++) {
                System.out.println((char) byt[i]);
            }
            // 使用完关闭流
            fis.close();
    }

    1.4.  输入流读取方式4:

    使用缓冲(提高效率),并循环读取(读完所有内容).

    总结:读完文件的所有内容。很显然可以使用普通的read方法,一次读一个字节直到读到文件末尾。为了提高效率可以使用read(byte[] byt);方法就是所谓的使用缓冲提高效率。我们可以读取大文本数据测试(大于1K的文本文件.)

    /**
         * 使用字节数组当缓冲
         * */
        private static void showContent5(String path) throws IOException {
            FileInputStream fis = new FileInputStream(path);
            byte[] byt = new byte[1024];
            int len = fis.read(byt);
            System.out.println(len);
            String buffer = new String(byt, 0, len);
            System.out.print(buffer);
        }

    注意:如何将字节数组转成字符串? 可以通过创建字符串对象即可。

    发现:一旦数据超过1024个字节,数组就存储不下。

    如何将文件的剩余内容读完?

    我们可以通过通过循环保证文件读取完。

    /**
         * 使用字节数组当缓冲
         * */
        private static void showContent7(String path) throws IOException {
            FileInputStream fis = new FileInputStream(path);
            byte[] byt = new byte[1024];
            int len = 0;
            while ((len = fis.read(byt)) != -1) {
                System.out.println(new String(byt, 0, len));
            }
        }
    author@nohert
  • 相关阅读:
    Easy | LeetCode 154 | 剑指 Offer 11. 旋转数组的最小数字 | 二分法
    Easy | 剑指 Offer 17. 打印从1到最大的n位数 | 大数
    Easy | LeetCode 191 | 剑指 Offer 15. 二进制中1的个数 | 位运算
    Easy | 剑指 Offer 57
    Medium | LeetCode 15. 三数之和 | 双指针法
    jq load()方法实现html 模块化。
    vue 剪切图片上传头像,使用 cropperjs 实现
    vue 的nextTick的理解
    使用nodejs进行开发,concurrently模块,使我们同时执行多个命令。
    cookie生命周期expires 时间过期,但是cookie没有被浏览器清理的问题
  • 原文地址:https://www.cnblogs.com/gzgBlog/p/13624603.html
Copyright © 2020-2023  润新知