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()来了。

发数据:

  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. }

读数据:

  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源码摘出来的):

  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. private void fill() throws IOException {
  20. ..../其它
  21. int n;
  22. do {
  23. n = in.read(cb, dst, cb.length - dst); //实质
  24. } while (n == 0);
  25. if (n > 0) {
  26. nChars = dst + n;
  27. nextChar = dst;
  28. }
  29. }

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

在JavaI/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);
   }

关于java中BufferedReader的read()及readLine()方法的使用心得的更多相关文章

  1. Java:java中BufferedReader的read()及readLine()方法的使用心得

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

  2. java中BufferedReader 有什么用

    这个类就是一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提供读的效率而设计的. BufferedReader buffer ...

  3. java中获取日期和时间的方法总结

    1.获取当前时间,和某个时间进行比较.此时主要拿long型的时间值. 方法如下:  要使用 java.util.Date .获取当前时间的代码如下 Date date = new Date(); da ...

  4. java中遍历map对象的多种方法

    在Java中如何遍历Map对象   How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有ma ...

  5. java中常用的字符串的截取方法

    java中常用的字符串的截取方法   1.length() 字符串的长度 例:char chars[]={'a','b'.'c'}; String s=new String(chars); int l ...

  6. Java中的五种单例模式实现方法

    [代码] Java中的五种单例模式实现方法   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2 ...

  7. 谈谈java中遍历Map的几种方法

    java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下具体的用法以及各自的优缺点 先初始化一个map public ...

  8. Java中产生随机数的两个方法

    Java中产生随机数的两个方法 一.利用random方法来生成Java随机数. 在Java语言中生成Java随机数相对来说比较简单,因为有一个现成的方法可以使用.在Math类中,Java语言提供了一个 ...

  9. Java中创建数组的几种方法

    Java中创建数组的几种方法 public static void main(String[] args) { //创建数组的第一种方法 int[] arr=new int[6]; int intVa ...

随机推荐

  1. Xshell配置密钥公钥(Public key)与私钥(Private Key)登录

    ssh登录提供两种认证方式:口令(密码)认证方式和密钥认证方式.其中口令(密码)认证方式是我们最常用的一种,这里介绍密钥认证方式登录到linux/unix的方法. 使用密钥登录分为3步:1.生成密钥( ...

  2. Java8的lambda表达式和Stream API

    一直在用JDK8 ,却从未用过Stream,为了对数组或集合进行一些排序.过滤或数据处理,只会写for循环或者foreach,这就是我曾经的一个写照. 刚开始写写是打基础,但写的多了,各种乏味,非过来 ...

  3. 【Java基础】1、java中的instanceof

    instanceof是Java.php的一个二元操作符(运算符),和==,>,<是同一类东西.由于它是由字母组成的,所以也是Java的保留关键字.它的作用是判断其左边对象是否为其右边类的实 ...

  4. TestOps宣言

    TestOps   TestOps离不开敏捷 TestOps是测试驱动的一种延伸,它强调测试人员与运维人员沟通协作规范化的实践模式. DevOps的持续集成与持续交付,实现了从代码到服务的快速落地.而 ...

  5. 外边距塌陷 margin collapsing

    块的顶部外边距和底部外边距有时被组合(折叠)为单个外边距,其大小是组合到其中的最大外边距, 这种行为称为外边距塌陷(margin collapsing),有的地方翻译为外边距合并. 1.相邻的兄弟姐妹 ...

  6. 【读书笔记】iOS-“一心多用”利用多线程提升性能

    iPhone将具有支持不同类型多线程API的能力,这些API包括:POSIX线程,NSObject,NSThread和NSOperation. iPhone操作系统是一个真正的抢占式,多任务操作系统, ...

  7. 【读书笔记】iOS-优化iOS Web应用

    一,代码优化: 代码优化是任何优化技术的第一步,因为归根结底网页上的一切都是构建在代码之上的.优秀的代码可以节省宽带,减少渲染延迟,以及提高页面的可读性和长远的可维护性.下面列出了一些在Web应用中编 ...

  8. CSS盒模型的介绍

    CSS盒模型的概念与分类      CSS盒模型就是一个盒子,封装周围的HTML元素,它包括内容content.边框border.内边距padding.外边距margin. CSS盒模型分为标准模型和 ...

  9. 【转】解决configure: error: C++ compiler cannot create executables问题

    转自:http://www.coderbolg.com/content/83.html 啊……天啊,./configure时报错:configure: error: C++ compiler cann ...

  10. 通用triggerEvent方法

    假设有一个id为testA的a元素,然后有以下代码(jquery已存在): $(document).ready(function(){ $('#testA').on('testEvent', func ...