被readLine()折腾了一把
虽然写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()的实质(下面是从JDK源码摘出来的):
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"来进行数据处理。
在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(),以免为了等待一个换行/回车符而一直阻塞
被readLine()折腾了一把的更多相关文章
- 转载:readLine()与read()
版权声明:本文为原博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sinat_31057219/article/details/78742653 参考: readLi ...
- VNC connect:Connection refused(10061)
在Windows机器上使用VNC Viewer访问Linux服务器,有时候会遇到"connect:Connection refused(10061)"这个错误,导致这个错误出现的原 ...
- svn co 与ssl
默认情况下, yum安装的svn用的是GnuTLS, 而不是ssl, 导致checkout https协议打包的svn repo的时候会报错. 解决方法是用openssl重新编译安装svn.注意ssl ...
- hadoop MapReduce 工作机制
摸索了将近一个月的hadoop , 在centos上配了一个伪分布式的环境,又折腾了一把hadoop eclipse plugin,最后终于实现了在windows上编写MapReduce程序,在cen ...
- 升级win10的理由
微软也没给我钱,我免费给它打了次广告. 我还是非常喜欢linux的,无奈公司深度依赖windows. 废话不多说,直接进入主题: [开机速度] 这里先说句题外话,不那么缺钱的兄弟,一定要去换一块SSD ...
- 全面解读Python Web开发框架Django
全面解读Python Web开发框架Django Django是一个开源的Web应用框架,由Python写成.采用MVC的软件设计模式,主要目标是使得开发复杂的.数据库驱动的网站变得简单.Django ...
- TrueCrypt
其实很早之前就知道这个软件,不过之前没有使用,今天折腾了一把,记录下使用过程中遇见的一些问题. 百度百科: TrueCrypt,是一款免费开源的加密软件,同时支持Windows Vista,7/XP, ...
- 在macos上基于python2.7安装PyQt5
在python3上面安装PyQt5是十分简单的,可是,在python2.7上安装这个东西,着实让人折腾了一把.要总结一下,年纪大了,记性不好. 首先要安装最新版的Qt和python2,命令如下: br ...
- Python Web开发框架Django
花了两周时间,利用工作间隙时间,开发了一个基于Django的项目任务管理Web应用.项目计划的实时动态,可以方便地被项目成员查看(^_^又重复发明轮子了).从前台到后台,好好折腾了一把,用到:HTML ...
随机推荐
- python脚本执行报错:SyntaxError: Non-ASCII character '\xe6' in file ip.py on line 4...
报错信息 [root@chenbj ~]# python ip.py 192.168.1.1 File "ip.py", line 4 SyntaxError: Non-ASCII ...
- 【6.20校内test】
反正考的不是很好吧,赶脚炸了啊qwq 然后这两天一直在忙一些神奇的事情,所以没有整理完 手动@water_lift T1:大美江湖: [题目背景] 细雪飘落长街,枫叶红透又一年 不只为故友流连,其实我 ...
- 循环 -----JavaScript
本文摘要:http://www.liaoxuefeng.com/ JavaScript的循环有两种,一种是for循环,通过初始条件.结束条件和递增条件来循环执行语句块: var x = 0; var ...
- 03_15_interface
03_15_interface 1. 接口 接口是抽象方法和常量值的定义的集合. 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现. 2. 接口特性 接口 ...
- java基础必备单词讲解 day one
computer 电脑 computer path 路径 配置jdk环境 class 类 classpath 类路径 编译好的文件执行路径 public 公共的 private 私有的 static ...
- iOS启动原理及应用生命周期
ios程序启动原理及生命周期图: ios应用程序的入口是main.m 1 #import <UIKit/UIKit.h> 2 3 #import "WYSAppDelegate. ...
- 1911: [Apio2010]特别行动队
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 5706 Solved: 2876[Submit][Status][Discuss] Descriptio ...
- Linux系统故障分析与排查--日志分析
处理Linux系统出现的各种故障时,故障的症状是最先发现的,而导致这以故障的原因才是最终排除故障的关键.熟悉Linux系统的日志管理,了解常见故障的分析与解决办法,将有助于管理员快速定位故障点,“对症 ...
- php实现的三个常用加密解密功能函数示例
目录 算法一: 算法二: 算法三(改进第一个加密之后的算法) 本文实例讲述了php实现的三个常用加密解密功能函数.分享给大家供大家参考,具体如下: 算法一: //加密函数 function lock_ ...
- [译]The Python Tutorial#10. Brief Tour of the Standard Library
[译]The Python Tutorial#Brief Tour of the Standard Library 10.1 Operating System Interface os模块为与操作系统 ...