經過調節buffer大小能夠達到調節讀入速率!當流沒有徹底讀入結束時,會循環讀入。java
一、內存大小爲100時:
json
二、 內存大小爲10時:緩存
當buffer的大小不一樣時,單次讀入的內容長度不一樣。app
同理於buffer的outputStream的write。測試
使用BIO的read()方式讀取時,若是對於複用的緩衝區byte[]不主動清除,將出現重複數據!ui
對於NIO的byteBuffer而言,在使用的時候結合get、flip、clear方法能夠經過控制內部的索引位置來讀寫,避免出現重複數據google
文件中數據: RemoteService.queryInnerFactorValuespa
主動清空!code
package com.noob.learn.test; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import com.alibaba.fastjson.JSONObject; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Lists; /** * 通過測試發現,BIO/NIO的單次的讀入多少由定義的buffer大小決定。數據長度沒有超出buffer大小將會一次性讀入 * <p> * TODO readLine並read 讀入差了1萬條???!!!! * * @author noob */ @Slf4j public class Test { public static void main(String[] args) throws IOException { new Test().analysis("2018"); } public String analysis(String mark) throws IOException { FileOutputStream fout = null; try { test("C:\\Users\\noob\\Desktop//report1.txt"); String method = analysis1("C:\\Users\\noob\\Desktop//method.txt", "methodName"); File file = new File("C:\\Users\\noob\\Desktop//report.txt"); if (!file.exists()) { file.createNewFile(); } fout = new FileOutputStream(file, true); StringBuilder sb = new StringBuilder(Strings.nullToEmpty(mark)).append("\n") .append("-------------method---------").append("\n").append(method).append("\n").append("\n"); fout.write(sb.toString().getBytes()); } catch (Exception e) { log.error("解析:{} 異常!", mark, e); } finally { if (fout != null) fout.close(); } return "success"; } /** * @param filePath * @throws Exception */ private void test(String filePath) throws Exception { BufferedInputStream br = new BufferedInputStream(new FileInputStream(filePath)); byte[] buffer = new byte[15]; //改變該長度能夠控制一次新讀入的數據量大小 StringBuilder sb = new StringBuilder(); while (br.read(buffer) != -1) { String str = new String(buffer); if (!Strings.isNullOrEmpty(str)) sb.append(str); //當數據總長度爲36時,按複用buffer,且不主動重置buffer的用法,最後輸出的值會有重複! 因此須要本身主動清除! Arrays.fill(buffer, (byte) 0); } System.out.println(sb); } private String analysis2(String filePath, String mark) throws IOException { ByteBuffer directBuffer = ByteBuffer.allocate(100);//改變該長度能夠控制一次新讀入的數據量大小 FileChannel fin = null; String result = null; try { fin = new FileInputStream(filePath).getChannel(); StringBuilder sb = new StringBuilder(); while (fin.read(directBuffer) != -1) { directBuffer.flip(); byte[] bytes = new byte[directBuffer.remaining()]; directBuffer.get(bytes); String str = new String(bytes, "UTF-8"); if (!Strings.isNullOrEmpty(str)) sb.append(str); directBuffer.clear(); // 重置緩衝區的索引位置。防止數據重複 (需結合get、flip的概念一塊兒理解) } result = analysis(mark, Splitter.on("\n").splitToList(sb).stream().map(t -> JSONObject.parseObject(t)) .filter(t -> t != null).collect(Collectors.toList())); } catch (Exception e) { e.printStackTrace(); } finally { if (fin != null) fin.close(); directBuffer = null; } return result; } private String analysis1(String filePath, String mark) throws IOException { BufferedReader fin = null; String result = null; try { fin = new BufferedReader(new InputStreamReader(new FileInputStream(filePath))); List<JSONObject> list = Lists.newArrayList(); String line = null; while ((line = fin.readLine()) != null) { list.add(JSONObject.parseObject(line)); } result = analysis(mark, list); } catch (Exception e) { log.error("解析:{} 異常!", filePath, e); } finally { if (fin != null) fin.close(); } return result; } private String analysis(String mark, List<JSONObject> list) { String key = "costTime"; int totalCount = list.size(); List<String> msg = Lists.newArrayList(); list.stream().collect(Collectors.groupingBy(t -> t.getString(mark))).entrySet().forEach(entry -> { String str = "%s, total:%s, avg:%s, max:%s, min:%s, lt_avg:%s, >50:%s, >100:%s, >200:%s, >300:%s, >500:%s"; List<JSONObject> value = entry.getValue(); int total = value.size(); String name = entry.getKey(); double avg = value.stream().mapToDouble(t -> t.getDouble(key)).average().getAsDouble(); double max = value.stream().mapToDouble(t -> t.getDouble(key)).max().getAsDouble(); double min = value.stream().mapToDouble(t -> t.getDouble(key)).min().getAsDouble(); double lavg = value.stream().filter(t -> t.getDouble(key) > avg).count(); double p50 = value.stream().filter(t -> t.getDouble(key) > 50).count(); double p100 = value.stream().filter(t -> t.getDouble(key) > 100).count(); double p200 = value.stream().filter(t -> t.getDouble(key) > 200).count(); double p300 = value.stream().filter(t -> t.getDouble(key) > 300).count(); double p500 = value.stream().filter(t -> t.getDouble(key) > 500).count(); msg.add(String.format(str, name, total, scale(avg), max, min, lavg, p50, p100, p200, p300, p500)); }); return "總條數:" + totalCount + "\n" + Joiner.on("\n").join(msg); } private String scale(double arg) { return new BigDecimal("" + arg).setScale(2, RoundingMode.HALF_UP).toString(); } }