java IO 使用細節

buffer大小能夠達到調節讀寫速率

經過調節buffer大小能夠達到調節讀入速率!當流沒有徹底讀入結束時,會循環讀入java

驗證步驟

一、內存大小爲100時:
json

二、 內存大小爲10時:緩存

結論

當buffer的大小不一樣時,單次讀入的內容長度不一樣。app

同理於buffer的outputStream的write。測試

BIO的read()須要每次讀入後主動清空緩存

使用BIO的read()方式讀取時,若是對於複用的緩衝區byte[]不主動清除,將出現重複數據!ui

 對於NIO的byteBuffer而言,在使用的時候結合get、flip、clear方法能夠經過控制內部的索引位置來讀寫,避免出現重複數據google

驗證步驟

    文件中數據: RemoteService.queryInnerFactorValuespa

解決方法

主動清空!code

 

 注意readLine的使用方式!

代碼

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();
    }
}
相關文章
相關標籤/搜索