我的编程空间,编程开发者的网络收藏夹
学习永远不晚

解决BufferedReader.readLine()遇见的坑

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

解决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) { 
		    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

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

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

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

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

解决BufferedReader.readLine()遇见的坑

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

开启Selinux遇到的坑及解决

这篇文章详细介绍了开启SELinux时可能遇到的常见问题和解决办法,包括:selinuxfs未挂载、策略不兼容、更新问题、上下文不正确、布尔值错误配置、审计记录已满、权限拒绝和导致系统无法启动。本文提供了针对每个问题的具体解决方案,包括挂载selinuxfs、检查策略、强制安装更新、设置正确上下文、修改布尔值、增加队列大小、授予权限和禁用SELinux。
开启Selinux遇到的坑及解决
2024-04-02

MyBatis+MyBatisPlus中遇到的坑怎么解决

这篇文章主要介绍了MyBatis+MyBatisPlus中遇到的坑怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇MyBatis+MyBatisPlus中遇到的坑怎么解决文章都会有所收获,下面我们一起来看
2023-07-05

Golang中JSON遇到的坑如何解决

本篇内容主要讲解“Golang中JSON遇到的坑如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Golang中JSON遇到的坑如何解决”吧!空指针会被解析成字符串"null"type Pe
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录