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()`是Java中可用于从输入流中读取一行文本的方法。它被称为"阻塞"是因为当调用这个方法时,如果没有可用的数据可以读取,程序将会被阻塞,即暂停执行直到有数据可用或者遇到异常。 当没有可用的数据时,`BufferedReader.readline()`方法将等待输入流中有足够的数据可供读取。这通常发生在以下情况下: 1. 输入流没有数据可供读取。例如,当程序正在读取一个空文件或者网络连接没有收到数据时,`BufferedReader.readline()`方法将一直阻塞。 2. 输入流的数据速度比程序读取的速度快。当程序没有及时读取输入流中的数据,输入流可能会积累一定量的数据。当程序准备好读取时,`BufferedReader.readline()`方法将会读取所有可用的数据行。 3. 输入流的数据被缓冲。在某些情况下,输入流可能会被缓冲以提高读取性能。当调用`BufferedReader.readline()`时,如果还没有足够的数据行在缓冲区中,此方法将阻塞直到有足够的数据行可供读取。 需要注意的是,阻塞是一种同步的行为,这意味着当程序在执行`BufferedReader.readline()`时会暂停执行,直到特定条件满足或者发生异常。因此,在使用`BufferedReader.readline()`方法时,我们需要注意处理可能的阻塞情况,例如使用多线程处理输入流或者设置适当的超时时间来避免长时间的阻塞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值