流的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);
}
複製代碼
相關文章
相關標籤/搜索