背景: 项目中采用了BufferedReader, 调用readline()方法读取流中的一行,导致代码在编译时对readline() 方法报了CodeDex, 为了清理CodeDex,坑就挖出来了。
1. 挖坑
代码原来大概是这样的:
public class MyTest1 {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\Administrator\\Desktop\\myTest1.txt");
InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bf = new BufferedReader(isr);
String line;
StringBuilder sb = new StringBuilder();
while(null != (line = bf.readLine())) {
sb.append(line).append("\n"); //注意readline时会把换行符弄没了
}
System.out.println(sb.toString());
}
}
整改后的代码大概是这样子的:
public class MyTest {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\Administrator\\Desktop\\myTest1.txt");
InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is);
StringBuilder sb = new StringBuilder();
char[] buffer = new char[200];
while (-1 != isr.read(buffer)) {
//这样代码是有问题的.......
sb.append(buffer);
}
String result = sb.toString();
System.out.println(result);
isr.close();
is.close();
}
}
2. 分析
最后的结果总是不对,大概扫了结果发现最后的内容不是真正末尾的内容,以为是读少了,各种折腾。。最后沉下心来,才发现是读多了。为什么呢?
InputStreamReader.read(char[] buffer)方法,其实是将每次从流中读到的内容按照顺序依次赋值给buffer[0], buffer[1],buffer[2]…, 前几次由于内容多,buffer小,每次循环读取都把 buffer[0] 到 buffer[buffer.length-1] 全部赋值了,没问题。。
等到最后一次读的时候, 流的内容就没有整个buffer可以容纳的多了, 可能读取的时候把 buffer[0] 到 buffer[n] 位置重新赋值, 这个时候, buffer[n+1] 到 buffer[buffer.length-1] 还是上次的旧值。。 (0 < n < = buffer.length-1)
再看:
我们每次是StringBuilder.append(char[] bufffer) 方法,把整个buffer append进去的,最后一次也不例外。。, 这就导致了最终得到的字符串 读多了。。。。
3. 解决办法
解决办法如下:
public class MyTest {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\Administrator\\Desktop\\myTest1.txt");
InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is);
StringBuilder sb = new StringBuilder();
char[] buffer = new char[200];
int len;
while (-1 != (len = isr.read(buffer))) {
//调用append(char[] str, int offset, int len) 方法,注意第三个参数len是流真正读取的长度
//另外注意该方法与append(char[] str)方法的区别
sb.append(buffer, 0, len);
}
String result = sb.toString();
System.out.println(result);
isr.close();
is.close();
}
}
注意的地方在代码里已经标注了。
这次填坑花了不少时间,特此记录一下。
睡觉了。。