阅读 540

解决BufferedReader.readLine()遇见的坑

这篇文章主要介绍了解决BufferedReader.readLine()遇见的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

目录
  • BufferedReader.readLine()遇见的坑

    • 今天踩了这个坑,所以做个笔记

    • 所以使用readLine()一定要注意

  • BufferedReader.readLine解析

    BufferedReader.readLine()遇见的坑

    在写ftp上传文件至服务器的过程中,有这样一个判断:判断某个文件夹下有多少个文件,内容为null的文件不上传,所以利用BufferedReader读取文件的内容,判断是否为null,所以用到了BufferedReader.readLine(),结果竟然卡死:txt、word、Excle、Ftp文件等都没有问题,但是读取MP3、Rar、zip等文件时,就一直处于卡死状态,先看代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    package com.test;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
      
    public class TestCh {
        public void readDocFileToFtp() {
            String docPath = "H:\\11"; // 文件所在路径 模拟
            File file;
            try {
                file = new File(docPath);
                File[] files = file.listFiles();
                if (files.length == 0) {
                    System.err.println(docPath + "文件夹下没有任何文件!");
                } else {
                    Arrays.sort(files);
                    System.err.println("文件数---" + files.length);
                    for (int i = 0; i < files.length; i++) {
                        if (files[i].isFile()) {
                            InputStreamReader reader;
                            reader = new InputStreamReader(new FileInputStream(files[i]));
                            BufferedReader br = new BufferedReader(reader);
                            String message = "";
                            String line = "";
                            long startTime = System.currentTimeMillis(); // 获取开始时间
                            while ((line = br.readLine()) != null) {
                                message += line;
                            }
                            br.close();
                            long endTime = System.currentTimeMillis(); // 获取结束时间
                            System.out.println("程序运行时间: " + (endTime - startTime) / 1000 + "ms");
      
                            String fileName = files[i].getName();
      
                            if (message.trim() == null || message.length() == 0) {
                                System.err.println(fileName + "文件内容为空!");
                            } else {
                                // 上传文件
                                System.err.println("上传===============");
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
         
        public static void main(String[] args) {
            TestCh te = new TestCh();
            te.readDocFileToFtp();
        }
    }

    然后一直卡死:

    我们都知道,readLine()方法是遇到换行符或者是对应流的结束符,该方法才会认为读到了一行(才会结束其阻塞),让程序继续往下执行。但可能因为以前不留意,也没遇见过这种情况,所以就认为该方法可放心使用

    今天踩了这个坑,所以做个笔记

    我们可能下意识地认为readLine()读取到没有数据时就返回null(因为read()方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null。

    readLine()只有在数据流发生异常或者另一端被close()掉时,才会返回null值。

    如果不指定buffer大小,则readLine()使用的buffer有8192个字符。

    在达到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才会返回。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    String readLine(boolean ignoreLF) throws IOException {
        StringBuffer s = null;
        int startChar;
            synchronized (lock) {
                ensureOpen();
            boolean omitLF = ignoreLF || skipLF;
            bufferLoop:
            for (;;) {
            if (nextChar >= nChars)
                fill(); //在此读数据
            if (nextChar >= nChars) { /* EOF */
                if (s != null && s.length() > 0)
                return s.toString();
                else
                return null;
            }
          ......//其它
    }
      
    private void fill() throws IOException {
        ..../其它
        int n;
        do {
            n = in.read(cb, dst, cb.length - dst); //实质
        } while (n == 0);
        if (n > 0) {
            nChars = dst + n;
            nextChar = dst;
        }
        }


    通过查看源码可知,readLine()是调用了read(char[] cbuf, int off, int len) 来读取数据,后面再根据"/r"或"/n"来进行数据处理

    所以使用readLine()一定要注意

    1.读入的数据要注意有/r或/n或/r/n

    2.没有数据时会阻塞,在数据流异常或断开时才会返回null

    3.非必要时(socket之类的数据流),要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞

    BufferedReader.readLine解析

    bufferedreader.readline()加载流程:

    1
    br = new BufferedReader(reader,510241024);//设置缓存大小:5M

    根据指定缓存大小,或默认缓存大小,读取文件内容放到缓存中,在将缓存数据放在内存中进行读取,等前一批内存中的数据读取完成后,

    下一批缓存数据会放在内存中进行读取;

    按行读取时等待读取到换行符返回内容;

    注意:以上内容都是自己理解的,仅为个人经验,希望能给大家一个参考

    原文链接:https://blog.csdn.net/weixin_39309402/article/details/99717386


    文章分类
    百科问答
    版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
    相关推荐