关于java中BufferedReader的read()及readLine()方法的使用心得

BufferedReader的readLine()方法是阻塞式的, 如果到达流末尾, 就返回null, 但如果client的socket末经关闭就销毁, 则会产生IO异常. 正常的方法就是使用socket.close()关闭不需要的socket.

 

从一个有若干行的文件中依次读取各行,处理后输出,如果用以下方法,则会出现除第一行外行首字符丢失现象

String str  = null;
br=new BufferedReader(new FileReader(fileName));
do{
  str = buf.readLine()); 
}while(br.read()!=-1);
以下用法会使每行都少首字符
while(br.read() != -1){
       str = br.readLine();     
 }
原因就在于br.read() != -1 这判断条件上。 因为在执行这个条件的时候其实它已经读取了一个字符了,然而在这里并没有对读取出来的这个字符做处理,所以会出现少一个字符,如果你这里写的是while(br.readLine()!=null)会出现隔一行少一行!

建议使用以下方法
String str = null;
      while((str = br.readLine()) != null){
      //System.out.println(str);//此时str就保存了一行字符串
}

这样应该就可以无字符丢失地得到一行了

 

 

虽然写IO方面的程序不多,但BufferedReader/BufferedInputStream倒是用过好几次的,原因是:

  • 它有一个很特别的方法:readLine(),使用起来特别方便,每次读回来的都是一行,省了很多手动拼接buffer的琐碎;
  • 它比较高效,相对于一个字符/字节地读取、转换、返回来说,它有一个缓冲区,读满缓冲区才返回;一般情况下,都建议使用它们把其它Reader/InputStream包起来,使得读取数据更高效。
  • 对于文件来说,经常遇到一行一行的,特别相符情景。

这次是在蓝牙开发时,使用两个蓝牙互相传数据(即一个发一个收),bluecove这个开源组件已经把数据读取都封装成InputStream了,也就相当于平时的IO读取了,很自然就使用起readLine()来了。

 

发数据:

 

[java] view plaincopy
  1. BufferedWriter output = new BufferedWriter(new OutputStreamWriter(conn.openOutputStream()));   
  2. int i = 1;  
  3. String message = "message " + i;  
  4. while(isRunning) {  
  5.     output.write(message+"/n");   
  6.     i++;  
  7. }  

 

 

 

读数据:

 

[java] view plaincopy
  1. BufferedReader input = new BufferedReader(new  InputStreamReader(m_conn.openInputStream()));  
  2. String message = "";  
  3. String line = null;  
  4. while((line = m_input.readLine()) != null) {  
  5.     message += line;  
  6. }  
  7. System.out.println(message);  

 

 

 

上面是代码的节选,使用这段代码会发现写数据时每次都成功,而读数据侧却一直没有数据输出(除非把流关掉)。经过折腾,原来这里面有几个大问题需要理解:

  • 误以为readLine()是读取到没有数据时就返回null(因为其它read方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null;因为readLine()阻塞后,System.out.println(message)这句根本就不会执行到,所以在接收端就不会有东西输出。要想执行到System.out.println(message),一个办法是发送完数据后就关掉流,这样readLine()结束阻塞状态,而能够得到正确的结果,但显然不能传一行就关一次数据流;另外一个办法是把System.out.println(message)放到while循环体内就可以。
  • readLine()只有在数据流发生异常或者另一端被close()掉时,才会返回null值。
  • 如果不指定buffer大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才会返回。

readLine()的实质(下面是从JDK源码摘出来的):

 

[java] view plaincopy
  1. String readLine(boolean ignoreLF) throws IOException {  
  2.     StringBuffer s = null;  
  3.     int startChar;  
  4.         synchronized (lock) {  
  5.             ensureOpen();  
  6.         boolean omitLF = ignoreLF || skipLF;  
  7.         bufferLoop:  
  8.         for (;;) {  
  9.         if (nextChar >= nChars)  
  10.             fill(); //在此读数据  
  11.         if (nextChar >= nChars) { /* EOF */  
  12.             if (s != null && s.length() > 0)  
  13.             return s.toString();  
  14.             else  
  15.             return null;  
  16.         }  
  17.       ......//其它  
  18. }  
  19.   
  20. private void fill() throws IOException {  
  21.     ..../其它  
  22.     int n;  
  23.     do {  
  24.         n = in.read(cb, dst, cb.length - dst); //实质  
  25.     } while (n == 0);  
  26.     if (n > 0) {  
  27.         nChars = dst + n;  
  28.         nextChar = dst;  
  29.     }  
  30.     }  

 

从上面看出,readLine()是调用了read(char[] cbuf, int off, int len) 来读取数据,后面再根据"/r"或"/n"来进行数据处理。

 

在Java I/O书上也说了:

public String readLine() throws IOException
This method returns a string that contains a line of text from a text file. /r, /n, and /r/n are assumed to be line breaks and are not included in the returned string. This method is often used when reading user input from System.in, since most platforms only send the user's input to the running program after the user has typed a full line (that is, hit the Return key).
readLine() has the same problem with line ends that DataInputStream's readLine() method has; that is, the potential to hang on a lone carriage return that ends the stream . This problem is especially acute on networked connections, where readLine() should never be used.

 

小结,使用readLine()一定要注意:

  1. 读入的数据要注意有/r或/n或/r/n
  2. 没有数据时会阻塞,在数据流异常或断开时才会返回null
  3. 使用socket之类的数据流时,要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞

 

 

 

以前学习的时候也没有太在意,在项目中使用到了才发现呵呵

1.读取一个txt文件,方法很多种我使用了字符流来读取(为了方便)

 

  FileReader fr = new FileReader("f:\\TestJava.Java");
   BufferedReader bf = new BufferedReader(fr);

//这里进行读取

int b;
   while((b=bf.read())!=-1){
    System.out.println(bf.readLine());
   }

发现每行的第一个字符都没有显示出来,原因呢:b=bf.read())!=-1  每次都会先读取一个字节出来,所以后面的bf.readLine());
读取的就是每行少一个字节

所以,应该使用

String valueString = null;
   while ((valueString=bf.readLine())!=null){
    
    
    System.out.println(valueString);
   }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDCVI——一种创新性的高清视频传输方案

什么是HDCVI 2012年11月,大华技术股份有限公司发布了具有自主知识产权的同轴高清传输接口技术HDCVI。HDCVI技术是一种基于已有SYV75-3或SYV75-5同轴电缆的高清视频传输方法,能够在低成本和较低质量的同轴电缆上实现超长距离高清视频信号的可靠传输。相比…

typedef struct 用法

如果在c程序中我们写:    typedef struct     {    int num;    int age;    }aaa,bbb,ccc;    这算什么呢?    我个人观察编译器(VC6)的理解,这相当于    typedef struct     …

智能机器人品牌简介

随着科技的发展,硬件的计算速度和大数据支撑,越来越多的智能化设备和产品出现在我们的面前,为我们的生活带来更多便利。其中包括智能机器人,这种产品是有自己的“大脑”,可以接收人为指令,为人服务&#xf…

转 Java对日期Date类进行加减运算一二三

请移步,https://blog.csdn.net/hacker_lees/article/details/74351838 ,感谢博主分享转载于:https://www.cnblogs.com/bestxyl/p/9790088.html

诞生之日 随笔

今天我诞生了,祝自己诞生日happy,happy,happy! 转载于:https://www.cnblogs.com/xiaohuihui-/p/7594406.html

智能音箱 之 麦克风参数介绍

1. 定义 麦克风,学名为传声器,是将声音信号转换为电信号的能量转换器件;声—电转换。 与扬声器正好相反(电—声转换),构成电声设备的两个终端,俗称咪头,麦克等。 是电声系统的入口&a…

大屏幕行业发展现状以及趋势深刻剖析

浏览数: 689 海康威视:叶志龙 中国投影网:大屏幕显示作为安防领域重要一环,而海康威视作为安防领域的佼佼者,请介绍海康威视大屏显示系统DLP/LCD这两大产品线?与行业同类产品相比,海康威视大屏拼接单元产品…

架构师是大忽悠吗?阿里技术大牛告诉你真相!

来源:阿里云 作者:林昊(花名毕玄),阿里巴巴技术保障部研究员,曾任淘宝网平台架构部架构师。个人的研究方向主要为Java模块化、动态化系统的构建,以及高性能大型分布式Java系统构建,主…

动手动脑-Java重载

有以下例子: 例: Using overloaded methods public class MethodOverload { public static void main(String[] args) { System.out.println("The square of integer 7 is " square(7)); System.out.println("\nThe square of double 7.…

利用django框架,手把手教你搭建数据可视化系统(一)

如何使用django去构建数据可视化的 web,可视化的结果可以呈现在web上。 使用django的MTV模型搭建网站 基础铺垫—MTV模型 Created with Raphal 2.1.0Request服务器(Djangoweb)Response首先,要搞清楚我们去访问服务器,服务器返回信…

智能音箱 之 扬声器喇叭介绍

在全双工语音交互的系统中,功放的质量是非常重要的,因为AEC回声消除对信号失真 是非常敏感的。音频通路的整体谐波失真需要控制在5%以内。 对于整个系统的谐波失真来说,扬声器是最关键的因素,其次是功放,麦克风的很小…

关于拓扑排序的问题-P3116 [USACO15JAN]会议时间Meeting Time

https://www.luogu.org/problem/show?pid3116 这道题目很水啊,但是我没有1A,而且wa了好多; 题目意思我就不讲了; 反正就是一个拓扑序dp; 但是这道题目规定了起点是1; 所以我一开始直接把1放进队列里然…

HD-SDI DVR发展与应用剖析

自2010年以来,视频监控已经进入“高清”监控时代;随着高清的发展,HD-SDI高清数字系统开始进入人们的视线,在大、小展会上均可以轻松找到“数字高清”的产品和解决方案。作为HD-SDI系统中编码、存储部分的HD-SDI高清数字硬盘录像机…

UML学习——类图(三)

1.类图 UML类图是用来描述类、接口、协作及它们之间的关系的图。用来显示系统中各个类的静态结构。 2.类图的组成元素 类图由以下六种元素组成:类,接口,泛化关系,关联关系,依赖关系,实现关系。 3.类图的绘制…

传锤子科技解散成都分公司 才搬迁一年罗永浩就顶不住了

雷帝网 乐天 10月16日报道今日有网友爆料,锤子科技解散成都分公司。有网友指出,爆料的人是锤子科技早期员工王前闯。网友爆料锤子成都研发中心解散网友爆料锤子成都研发中心解散2016年,锤子科技亏损4亿元,一直徘徊在破产的边缘&am…

智能音箱 之 功放与扬声器(喇叭)的匹配关系

1. 功放的概念   功率放大器简称功放,俗称 “扩音机”,是音响系统中最基本的设备,它的任务是把来自信号源(专业音响系统中则是来自调音台)的微弱电信号进行放大以驱动扬声器发出声音。 2. 功放的分类 功率放大器分…

前端性能优化 Web前端应该从哪些方面来优化网站?

作者:斯迪链接:https://www.zhihu.com/question/21658448/answer/18903129来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。前端是庞大的,包括 HTML、 CSS、 Javascript、Image 、Flash…

嵌入式NVR发展浅析

随着视频监控的高速发展,视频监控对硬盘录像机的要求也在不断提高,在以往“看得见”的基础上,要求视频画面看的更为清晰、准确。相对于传统硬盘录像机,NVR最主要的特征就是“网络化”、“高清化”,在视频监控“高清化”…

Maven and Nexus2

2019独角兽企业重金招聘Python工程师标准>>> Maven and Nexus2 Maven是什么? 构建工具: 通过简单的命令,能够完成清理、编译、测试、打包、部署等一系列过程。同时,不得不提的是,Maven是跨平台的&#xff0…

Linux kernel的中断子系统之(九):tasklet

返回目录:《ARM-Linux中断系统》。 总结: 二介绍了tasklet存在的意义。 三介绍了通过tasklet_struct来抽想一个tasklet,每个CPU维护一个tasklet链表tasklet_vec/tasklet_hi_vec,然后介绍了如何定一个一个tasklet(静态/动态)&#…