Java: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()来了。
发数据:
- 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"来进行数据处理。
小结,使用readLine()一定要注意:
- 读入的数据要注意有/r或/n或/r/n
- 没有数据时会阻塞,在数据流异常或断开时才会返回null
- 使用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:java中BufferedReader的read()及readLine()方法的使用心得的更多相关文章
- 关于java中BufferedReader的read()及readLine()方法的使用心得
BufferedReader的readLine()方法是阻塞式的, 如果到达流末尾, 就返回null, 但如果client的socket末经关闭就销毁, 则会产生IO异常. 正常的方法就是使用sock ...
- java开发中遇到的问题及解决方法(持续更新)
摘自 http://blog.csdn.net/pony12/article/details/38456261 java开发中遇到的问题及解决方法(持续更新) 工作中,以C/C++开发为主,难免与其他 ...
- 【JAVA】Java 异常中e的getMessage()和toString()方法的异同
参考链接 CSDN: Java 异常中e的getMessage()和toString()方法的异同 示例代码1: public class TestInfo { private static ...
- java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态
刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...
- 一个java文件中可包含多个main方法
java中的main方法是java应用程序的入口,java程序在运行时,首先调用执行main方法.但并不是说java中只能有一个main方法,不同类中都可以包含main方法.当JVM进行编译时,会提示 ...
- java类中为什么设置set和get方法操作属性
java程序规范中会建议大家尽量将类中的属性私有化,即定义为private变量,通过设置set和get函数来对属性进行操作.一些人存在这样的疑问,为什么不直接将属性设置为public,以后调用属性时直 ...
- java学习过程中遇到的坑及解决方法
1. Table 'my_data_base.gjp_zhangwu' doesn't exist Query: select * from gjp_zhangwu Parameters: 数据库中的 ...
- Java多线程中join、yield、sleep方法详解
在Java多线程编程中,Thread类是其中一个核心和关键的角色.因此,对该类中一些基础常用方法的理解和熟练使用是开发多线程代码的基础.本篇主要总结一下Thread中常用的一些静态方法的含义及代码中的 ...
- Java语言中姐种遍历List的方法总结
遍历 List 的方法: 1. for 2. advanced for 3. Iterator 4. while 5. ListIterator List<E> list 1. for f ...
随机推荐
- 【物联网云端对接-4】通过MQTT协议与百度云进行云端通信
百度云的天工物联网服务目前包括:物接入.物解析.物管理.时序数据库和规则引擎等5大部分,本篇文章仅介绍物接入. 天工物联网的物接入,从开发者的角度来说相对有些复杂,需要多步操作才能实现一个云设备的创建 ...
- 【javascript】您好, 您要的ECMAScript6速记套餐到了
[前言]本文“严重参考” 自阮一峰老师写的文档,在此我郑重感谢他沉默无声的帮助 总结一下ES6为 javascript中的 对象/数组/函数 这JS三巨头所提供的更简洁优雅的书写方式,以及扩展的API ...
- VMware Workstation 12 Pro 之安装林耐斯StartOS X64系统
VMware Workstation 12 Pro 之安装林耐斯StartOS X64系统... ---------------- 先去下载系统暗中包ISO 网址:http://www.xiaza ...
- DOM-----style属性对照表
CSS和Java script 标签对照表 盒子标签和属性对照 CSS语法 (不区分大小写) Java script 语法 (区分大小写) border border border-bottom bo ...
- 缓存一致性和跨服务器查询的数据异构解决方案canal
当你的项目数据量上去了之后,通常会遇到两种情况,第一种情况应是最大可能的使用cache来对抗上层的高并发,第二种情况同样也是需要使用分库 分表对抗上层的高并发...逼逼逼起来容易,做起来并不那么乐观, ...
- Python学习笔记2
闭包 闭包用起来简单,实现起来可不容易. 另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行.我们来看一个例子: def count(): fs = [] for i in ...
- 为Ext添加下拉框和日期组件
Ext.onReady(function(){ var config = { fields:['module'], data:[['新建'],['删除'],['增加']}; var store = n ...
- django框架(Model)
-------------------使用MySql数据库-------------------1.进行对应mysql-python包的下载 pip install mysql-python 2.在m ...
- spring mvc:事务引起的try/catch失效
在测试一个接口时,发现一个奇怪的现象:该接口使用@ResponseBody注解返回json格式数据,并且使用try/catch包括全部逻辑代码,debug后发现返回数据没有任何错误,只包含一段因产生异 ...
- 向GitHub 提交你的源代码
之前的这篇文章「Git入门篇」相信大家都已经对 Git 的基本操作熟悉了,但是这篇文章只介绍了对本地 Git 仓库的基本操作,今天我就来介绍下如何跟远程仓库一起协作,教你们向 GitHub 上提交你们 ...