zoukankan      html  css  js  c++  java
  • 关于java中BufferedReader的read()及readLine()方法的使用心得

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

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

      它有一个很特别的方法:readLine(),使用起来特别方便,每次读回来的都是一行,省了很多手动拼接buffer的琐碎;

      它比较高效,相对于一个字符/字节地读取、转换、返回来说,它有一个缓冲区,读满缓冲区才返回;一般情况下,都建议使用它们把其它Reader/InputStream包起来,使得读取数据更高效。

      对于文件来说,经常遇到一行一行的,特别相符情景。

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

      发数据:

    BufferedWriter output = new BufferedWriter(new OutputStreamWriter(conn.openOutputStream()));   
    int i = 1;  
    String message = "message " + i;  
    while(isRunning) {  
        output.write(message+"/n");   
        i++;  
    } 

      读数据:

    BufferedReader input = new BufferedReader(new  InputStreamReader(m_conn.openInputStream()));  
    String message = "";  
    String line = null;  
    while((line = m_input.readLine()) != null) {  
        message += line;  
    }  
    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()一定要注意

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

    正确读取Socket InputStream 的方法

    package com.photoManage.utils;
    
    import java.io.*;  
    
    public class StreamTool {     
        public static void main(String[] args) {  
            try {  
                File file = new File("C:\demo.log");  
                FileInputStream fin = new FileInputStream(file);  
                byte[] filebt = readStream(fin);  
                System.out.println(filebt.length);  
            } catch (Exception e) {  
                e.printStackTrace();  
            }     
        }
        
        /** 
         * @功能 读取流 
         * @param inStream 
         * @return 字节数组 
         * @throws Exception 
         */  
        public static byte[] readStream(InputStream inStream) throws Exception {  
            int count = 0;
            while (count == 0) {
                count = inStream.available();
            }
            byte[] b = new byte[count];
            inStream.read(b);
            return b; 
        }  
    }  

    参考博客:

    http://cuisuqiang.iteye.com/blog/1434416#comments

  • 相关阅读:
    C# 操作配置文件
    C# Excel操作类
    没有找到 mspdb100.dll 的解决办法
    工厂方法模式
    .Net互操作2
    The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决
    手机抓包xcode自带命令行工具配合wireshark实现
    expecting SSH2_MSG_KEX_ECDH_REPLY ssh_dispatch_run_fatal问题解决
    使用ssh-keygen设置ssh无密码登录
    远程复制文件到服务器
  • 原文地址:https://www.cnblogs.com/jiafuwei/p/6742581.html
Copyright © 2011-2022 走看看