解决BufferedReader.readLine()遇见的坑

 更新时间:2021年12月09日 10:58:08   作者:南丘xf  
这篇文章主要介绍了解决BufferedReader.readLine()遇见的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

BufferedReader.readLine()遇见的坑

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

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"才会返回。

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()加载流程:

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

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

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

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

注意:以上内容都是自己理解的,仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java中list集合为空或为null的区别说明

    Java中list集合为空或为null的区别说明

    这篇文章主要介绍了Java中list集合为空或为null的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java guava monitor监视器线程的使用详解

    Java guava monitor监视器线程的使用详解

    工作中的场景中是否存在类似这样的场景,需要提交的线程在某个触发条件下执行。本文主要就是使用guava中的monitor来优雅的实现带监视器的线程
    2021-11-11
  • 一文读懂IDEA里面的Artifact到底是什么

    一文读懂IDEA里面的Artifact到底是什么

    这篇文章主要介绍了IDEA里面的Artifact到底是什么,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-01-01
  • java为移动端写接口开发实例

    java为移动端写接口开发实例

    本篇文章主要介绍了java如何为移动端写接口,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java实现快速排序过程分析

    Java实现快速排序过程分析

    今天小编就为大家分享一篇关于Java实现快速排序过程分析,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • Java File类的概述及常用方法使用详解

    Java File类的概述及常用方法使用详解

    Java File类的功能非常强大,下面这篇文章主要给大家介绍了关于Java中File类的概述及常用方法使用,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • java几种排序算法的实现及简单分析

    java几种排序算法的实现及简单分析

    这篇文章主要介绍了java几种排序算法的实现及简单分析,实例分析了插入排序、希尔排序、选择排序等常用排序算法,并分析了各个算法的优劣,需要的朋友可以参考下
    2015-05-05
  • Java中的lambda和stream实现排序

    Java中的lambda和stream实现排序

    这篇文章主要介绍了Java中的lambda和stream实现排序,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Java Stream 流实现合并操作示例

    Java Stream 流实现合并操作示例

    这篇文章主要介绍了Java Stream 流实现合并操作,结合实例形式详细分析了Java Stream 流实现合并操作原理与相关注意事项,需要的朋友可以参考下
    2020-05-05
  • Java 中String StringBuilder 与 StringBuffer详解及用法实例

    Java 中String StringBuilder 与 StringBuffer详解及用法实例

    这篇文章主要介绍了Java 中String StringBuilder 与 StringBuffer详解及用法实例的相关资料,需要的朋友可以参考下
    2017-02-02

最新评论