基于bufferedreader的read()与readline()读取出错原因及解决

目录
  • bufferedreader的read()与readline()读取出错
  • bufferedReader中的readLine()源码解析

bufferedreader的read()与readline()读取出错

以前学习java的时候也没有太在意,直到最近做项目时使用了才发现这个问题,总是第一个字符输不出来

bufferedreader这个类借用别人的话来说,就是一个包装类

它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提高读的效率而设计的。

读取一个txt文件,方法很多种而我使用的是字符流来读取

int c;
FileReader file = new FileReader("D:\\emDemo.java");
   BufferedReader br = new BufferedReader(file);
   while((c=br.read())!=-1){undefined
    System.out.println(br.readLine());
   }

发现每行的第一个字符都没有显示出来,后来发现 c=br.read())!=-1 每次都会先读取一个字节出来,所以后面的br.readLine());

读取的就是每行少一个字节

所以,应该使用

String input = null;
   while ((input=br.readLine())!=null){undefined
    System.out.println(input);
   }

这样就能解决了~

bufferedReader中的readLine()源码解析

String readLine(boolean ignoreLF) throws IOException {
		//行(hang)数据的缓冲s
		StringBuffer s = null;
		int startChar;

	        synchronized (lock) {
	       /*确保被bufferedReader包装的输入流没有关闭*/
	            ensureOpen();

	          /* 如果 读到'\r',skipLF置为true,
	           * 这是skip()方法里面的部分代码,它展示了通过skipLF来忽略'\n'
	           * if (skipLF) {
		        skipLF = false;
		        if (cb[nextChar] == '\n') {
			   	 	nextChar++;
		          }
		       }
	           *ignoreLF一直就是false
	           **/
		    boolean omitLF = ignoreLF || skipLF;

		 /* bufferLoop主要是不断地遍历底层的数组cb,并取两个换行符之间的数据付给行缓冲s。当底层数组遍历完要用fill()把数据从流中填充到cb,直到流的末尾
		  *charloop,主要是遍历缓冲数组cb,以确定'\n','\r'的位置
		    nextChar:下次读取缓冲字符数组cb的位置,
		  	nChars:缓冲字符数组cb的length

		  */
		    bufferLoop:
		    for (;;) {

		    	//1、如果缓冲数组的数据不足,或者已经读到了数组的末尾时:
		    	//1.1如果下次读取的位置已经到了or超过数组的长度,从流中读数据到缓冲数组cb中
			if (nextChar >= nChars)
			    fill();
			/*1.2如果从流中读数据到数组cb之后, nextChar,nChars的大小关系没有改变.
			说明到了文件的末尾,END OF FILE.返回s
			*/
			if (nextChar >= nChars) { /* EOF */
			    if (s != null && s.length() > 0)
				return s.toString();
			    else
				return null;
			}

			//2 缓冲数组中有足够的数据时:
			/*从本个换行符所在的索引位置开始,遍历char [] cb ,直到找到\n \r,把两个换行符之间的字符序列填充进s
			 *eol:END OF LINE
			 *类属性char [] cb ,也就是bufferReader类的缓冲数组。length由构造器指定,若不指定默认为8 * 1024 = 8192,与内存页大小密切相关
			 * */
			boolean eol = false;
			char c = 0;
			int i;

			if (omitLF && (cb[nextChar] == '\n'))
	                    nextChar++;
			skipLF = false;
			omitLF = false;

		    charLoop:
			for (i = nextChar; i < nChars; i++) {
			    c = cb[i];
			    if ((c == '\n') || (c == '\r')) {
				eol = true;
				break charLoop;
			    }
			}

			/*2.1找到换行符后,从上个换行符到本换行符之间的序列,填充给s*/
			startChar = nextChar;
			nextChar = i;
			if (eol) {
			    String str;
			    /*2.1.1如果是第一次遍历到换行符,*/
			    if (s == null)
			    {
				str = new String(cb, startChar, i - startChar);
			    }
			    /*2.1.2至少遍历到一次换行符时*/
			    else
			    {
				s.append(cb, startChar, i - startChar);
				str = s.toString();
			    }
			  //更新下次读取的位置
			    nextChar++;
			    if (c == '\r') {
				skipLF = true;
			    }
			    return str;
			}
			//2.2如果没有换行符
			if (s == null)
				//类属性int defaultExpectedLineLength = 80
			    s = new StringBuffer(defaultExpectedLineLength);
			//填充s,从上个换行符到最后
			s.append(cb, startChar, i - startChar);
		    }
	        }
	    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

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

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

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

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

  • 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流 流:流是一组有序的,有起点和终点的字节集合,是对计算机中数据传输的总称.

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

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

  • 基于bufferedreader的read()与readline()读取出错原因及解决

    目录 bufferedreader的read()与readline()读取出错 bufferedReader中的readLine()源码解析 bufferedreader的read()与readline()读取出错 以前学习java的时候也没有太在意,直到最近做项目时使用了才发现这个问题,总是第一个字符输不出来 bufferedreader这个类借用别人的话来说,就是一个包装类 它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提高读

  • Visual Studio 2017创建.net standard类库编译出错原因及解决方法

    正式版上个月已经Release了,从那时到现在经常会收到更新提示,估计问题还不少吧!其中最吸引我的当然是.net standard与.net core. 刚好最近接触.net standard项目,新建一个类库直接编译却出错!!立马心情不太好了,对它的兴趣大打折扣! 如果是新手估计立马就会吐槽了!作为老手还是静下心来看看原因. 看最后一项: 找不到资产文件"c:\users\newblifes\documents\visual studio 2017\Projects\TestDemo\Test

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

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

  • 基于python实现在excel中读取与生成随机数写入excel中

    具体要求是:在一份已知的excel表格中读取学生的学号与姓名,再将这些数据放到新的excel表中的第一列与第二列,最后再生成随机数作为学生的考试成绩. 首先要用到的数据库有:xlwt,xlrd,random这三个数据库. 命令如下: import xlwt import xlrd import random 现有一份表格内容如下图: 现在我们需要提取这其中的B1-C14. (提示:在对这份电子表格进行操作的时候,要使用到这个电子表格的地址,即表格的储存位置.) excel=xlrd.open_w

  • PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解

    本文实例讲述了PHP5.5基于mysqli连接MySQL数据库和读取数据操作.分享给大家供大家参考,具体如下: 在学习1. 开启PHP的API支持 (1)首先修改您的php.ini的配置文件. 查找下面的语句: ;extension=php_mysqli.dll 将其修改为: extension=php_mysqli.dll (2)重新启动Apache/IIS,即可. (3)说明:PHP需要单独的文件来支持这个扩展库,一般在PHP目录下的ext目录里能找到php_mysqli.dll文件(PHP

  • windows server2014 安装 Mysql Applying Security出错的完美解决方法

    原因就是安装一遍之后没有卸载干净. 解决这个问题需要注意以下几点: 1.手动清除以下文件确保卸载干净 1)mysql的安装目录,一般为C:/Program Files目录下. 2)mysql的数据存放目录,一般在C:/Documents and Settings/All Users/Application Data目录下(需要注意的时Application Data这个文件夹默认是隐藏的,要通过 工具->文件夹选项->查看->显示所有文件与文件夹 来设置隐藏文件可见). 3)除注册表数据

  • mysql5.x升级到mysql5.7后导入之前数据库date出错的快速解决方法

    mysql5.x升级至mysql5.7后导入之前数据库date出错的解决方法如下所示: 修改mysql5.7的配置文件即可解决,方法如下: linux版:找到mysql的安装路径进入默认的为/usr/share/mysql/中,进行对my-default.cnf编辑 利用查找功能"/"找到"sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES" 将其删除或者是注释即可. windows版:32位找到mysql安装路径

  • 基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法

    基于Bootstrap做的下拉菜单在电脑浏览器中可正常使用,在手机浏览器中能弹出下拉列表,却不能选择列表中的菜单项,通过自己百度查找原因将bootstrap脚本文件中的ontouchstart 替换为 disable-ontouchstart可以解决,替换后并不能解决.(红米手机UC浏览器不支持,小米手机UC浏览器正常,其他暂时未测试) jquery:v1.11.2 bootstrap:v3.3.4 以下为前台页面代码: <div class="input-group">

  • sql server定时作业调用Kettle job出错的快速解决方法

    错误信息: Unable to list jar files in plugin folder 'C:\Windows\system32\config\systemprofile\.kettle\plugins' Unable to get VFS File object for filename 'C:\Windows\system32\config\systemprofile\.kettle\plugins' : Could not find file with URI "C:\Window

  • 基于tomcat8 编写字符编码Filter过滤器无效问题的解决方法

    同事遇到编码问题时想做一个解决全站的字符编码过滤器,过滤器类和配置如下: 过滤器类: <span style="font-size:12px;">package com.chaoxing.newspaper.web.filter; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.r

随机推荐