流的read()方法返回的长度的重要性

前几天在定位生产问题时,因为日志中的JSON格式的List集合是不去重的,想看看去重后的数量,太长不能直接拷贝为String类型的值,就想着放到一个文件中写个main()读取转换下,发现明明读取应该结束了,可是最后的结果老是比文件中多那么些。最后发现是忽略了read()返回的len的问题,作个记录java

Main()方法

public static void main(String[] args) {

		try (FileReader reader = new FileReader(new File("E:\\ideaWorkspace\\testProject\\src\\main\\java\\test\\crowdList.txt"))){
			char[] buf = new char[100];
			int len;
			StringBuilder sb = new StringBuilder();
			while ((len = reader.read(buf)) != -1) {

				String str = new String(buf);
				sb.append(str);

			}

			List<String> strings = JSON.parseArray(sb.toString(), String.class);
			System.out.println(strings.size());
			Set<String> deSet = new HashSet<>(strings);
			System.out.println(deSet.size());


		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
复制代码

分析下

乍一看感受没啥问题,可是出错了,错误的内容是json

是阿里巴巴的fastJson报出来的说不是一个闭合的json字符串,可是文件中确实是个有开闭的符号的,咱们把每一行都打出来看看数组

咱们能够看到明明结束的打印出来以后,后边又打出来了一串,并且这一串和上边的如出一辙缓存

结论

到这边就能看出来了,最后一次read()确定是没有把咱们用来存储内容的数组装满就是代码中的buf,装了多少呢,其实就是从0开始len个长度,剩下的仍是上一次读取存在里边的,那就有两种思路了bash

  • 每次读取后清空缓存数组(每次初始化仍是有性能损失)
while ((len = reader.read(buf)) != -1) {
	String str = new String(buf);
	sb.append(str);
	buf = new char[100];
}
复制代码
  • 存储读取结果时只取前len个长度(读多少用多少,这个比较好)
while ((len = reader.read(buf)) != -1) {
	String str = new String(buf,0,len);
	sb.append(str);
}
复制代码
相关文章
相关标签/搜索