解决BufferedReader.readLine()遇见的坑

目录
  • BufferedReader.readLine()遇见的坑
    • 今天踩了这个坑,所以做个笔记
    • 所以使用readLine()一定要注意
  • 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

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

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

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

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

(0)

相关推荐

  • 基于自定义BufferedReader中的read和readLine方法

    实例如下所示: package day0208; import java.io.FileReader; import java.io.IOException; /* * 自定义读取缓冲区,实现BufferedReader功能 * 分析: * 缓冲区就是封装了一个数组,并对外提供了更多的方法对数组进行访问 * 其实这些方法最终操作的都是数组的角标 * 缓冲的原理: * 其实就是从源中获取一批数据装进缓冲区,再从缓冲区取出数据 * 当此次取完后,继续从源中取出一批数据到缓冲区 * 当源中的数据取光时

  • 解决bufferedReader.readLine()读到最后发生阻塞的问题

    bufferedReader.readLine()读到最后发生阻塞 最近在做一个imageserver,需求简化后就是使用socket响应HTTP请求从而截取所需要的数据流,写入到服务器端的文件中,从而完成客户端将图片上传到服务器. 因为从客户端得到的数据流中,我们只希望截取其中的一部分.这样就使我们无法像经常那样边读边向文件中写入,而且在流已经读到末尾时,使用bufferedInputStream.read()>0或inputStream.read()>0作为while语句结束的判断条件在使

  • 关于BufferedReader的read()和readLine()的区别

    目录 BufferedReader的read()和readLine()区别 小结一下 项目经验 BufferedReader.readLine()总结 正确的代码如下 BufferedReader的read()和readLine()区别 从一个有若干行deep文件中依次读取各行,处理后输出,如果用以下方法,则会出现除第一行外首字符丢失的现象 String str = null; br=new BufferedReader(new FileReader(fileName)); do{ str =

  • 解决BufferedReader.readLine()遇见的坑

    目录 BufferedReader.readLine()遇见的坑 今天踩了这个坑,所以做个笔记 所以使用readLine()一定要注意 BufferedReader.readLine解析 BufferedReader.readLine()遇见的坑 在写ftp上传文件至服务器的过程中,有这样一个判断:判断某个文件夹下有多少个文件,内容为null的文件不上传,所以利用BufferedReader读取文件的内容,判断是否为null,所以用到了BufferedReader.readLine(),结果竟然

  • 解决golang 关于全局变量的坑

    学习golang不久,在定义全局变量的时候遇见了坑.写个小例子,增强记忆. 错误版本 var p int func main() { p, err := test(4) if err != nil { log.Fatal(err) } } func test(i int) (int, error) { return i + 1, nil } 编译一直不通过,p declared and not used.后来查了查资料,看见这种其实是在main里边又重新定义了p,所以一直提示p定义了但是没有使用

  • Java IO及BufferedReader.readline()出现的Bug

    目录 Java IO及BufferedReader.readline()的Bug IO流 BufferedReader.readline()方法Bug 源码 使用BufferReader类的readLine()方法注意问题 一.BufferReader类的readLine()方法 二.DataInputStream类的readUTF()方法 Java IO及BufferedReader.readline()的Bug IO流 流:流是一组有序的,有起点和终点的字节集合,是对计算机中数据传输的总称.

  • vue-router之解决addRoutes使用遇到的坑

    最近项目中使用了vue-router的addRoutes这个api,遇到了一个小坑,记录总结一下. 场景复现: 做前端开发的同学,大多都遇到过这种需求:页面菜单根据用户权限动态生成,一个常见的解决方案是: 前端初始化的时候,只挂载不需要权限路由,如登陆,注册等页面路由,然后等用户登录之后,后端返回当前用户的权限表,前端根据这个权限表遍历前端路由表,动态生成用户权限路由,然后使用vue-router提供的addRoutes,将权限路由表动态添加到路由实例中,整个过程大致如下: // router.

  • 解决@SpringBootTest 单元测试遇到的坑

    目录 @SpringBootTest单元测试的坑 1.环境 2.遇到的问题 3.解决方式 Test类运行单元测试失效 Test测试类无法执行完全问题 @SpringBootTest单元测试的坑 1.环境 spring boot 版本:2.4.3 2.遇到的问题 (1)@Before.@After 失效 (2)org.junit.runners.model.InvalidTestClassError: 3.解决方式 注意 import 的 junit 包的配套问题 #junit5 配套 impor

  • 解决Android原生定位的坑

    Android原生定位的代码网上已经很多了,就不贴出来. 简单了解下: GPS_PROVIDER:通过手机内置的GPS芯片,利用卫星获取定位信息.位置监听.卫星状态监听很耗电且室内定位很不准确. NETWORK_PROVIDER:网络定位通过基站和WiFi节点,利用节点id在定位数据服务器查询位置信息.但是国内网络不允许,且有消息称Google已不提供该服务.so网上出现的此种方式获取定位信息不可用,也就是说NETWORK_PROVIDER在国内不可用. PASSIVE_PROVIDER:被动定

  • 解决python logging遇到的坑 日志重复打印问题

    python 中 logging模块 假如遇到 多线程 或者 多进程 或者在web框架中自定义logging的话(一个请求就是一个独立的线程)非常容易重复打印日志 和造成内存崩溃,所以: 解决方法如下: 重写日志方法 用类: class Log(): import logging def __init__(self): self.logger = logging.getLogger(__name__) # 以下三行为清空上次文件 # 这为清空当前文件的logging 因为logging会包含所有

  • 解决mybatis-plus自定义xml的坑

    目录 mybatis-plus自定义xml的坑 1.properties文件没有指明xml文件路径 2.没有扫描mapper的配置类 3.xml文件命名空间位置没写对 自定义xml的模板 mybatis-plus自定义xml的坑 1.properties文件没有指明xml文件路径 2.没有扫描mapper的配置类 3.xml文件命名空间位置没写对 自定义xml的模板 <?xml version="1.0" encoding="UTF-8" ?> <

  • java 使用readLine() 乱码的解决

    目录 使用readLine() 乱码的解决 本人在公司开发程序遇到了读取 一行乱码 小结一下 调用readLine的乱码问题 下面提供的是readLine字符流指定编码方式的方法 使用readLine() 乱码的解决 本人在公司开发程序遇到了读取 一行乱码 eclipse 默认为utf-8 FileInputStream f4 = new FileInputStream(new File("F:\\bb.txt")); BufferedReader bufferedReader2 =

随机推荐