解析 csv 文件并存储结果,因为 JFree 图表数据集消耗堆 space

Parse csv file and store result as JFree chart dataset consumes heap space

我有一个 Netbeans 模块应用程序,在我的 Netbeans IDE 中执行时 运行 没问题。 但是当我 运行 从生成的解压缩文件夹中分发可执行文件时,应用程序 swing worker 任务将在一段时间后停止。它循环遍历几个文件然后停止。 我最好的猜测是我必须对处理 csv 文件的循环做些什么?或者...任何 ide 或提示将不胜感激 文件的大小为 2000 - 600.000 行,包含 5 个定义为双精度的时间序列。 我将数据集存储在 collection.

这是我使用 while 循环的方法

protected XYDataset generateDataSet(String filePath) {

    TimeSeriesCollection dataset = null;
    try {
        dataset = new TimeSeriesCollection();

        boolean isHeaderSet = false;

        String fileRow;
        StringTokenizer tokenizer;
        BufferedReader br;
        List<String> headers;
        String encoding = "UTF-8";
        br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), encoding));

        //br = new BufferedReader(new FileReader(filePath));
        if (!br.ready()) {
            throw new FileNotFoundException();
        }
        fileRow = br.readLine();

循环从这里开始

        while (fileRow != null) {

            if (!isHeaderSet) {
                headers = getHeaders(fileRow);
                for (String string : headers) {
                    dataset.addSeries(new TimeSeries(string));
                }
                isHeaderSet = true;
            }
            if (fileRow.startsWith("#")) {
                fileRow = br.readLine();
            }
            String timeStamp = null;
            String theTok1 = null;
            String theTok2;
            tokenizer = new StringTokenizer(fileRow);
            if (tokenizer.hasMoreTokens()) {
                theTok1 = tokenizer.nextToken().trim();
            }
            if (tokenizer.hasMoreTokens()) {
                theTok2 = tokenizer.nextToken().trim();
                timeStamp = theTok1 + " " + theTok2;
            }

            Millisecond m = null;

            if (timeStamp != null) {
                m = getMillisecond(timeStamp);
            }

            int serieNumber = 0;
            br.mark(201);
            if (br.readLine() == null) {
                br.reset();
                while (tokenizer.hasMoreTokens()) {
                    if (dataset.getSeriesCount() > serieNumber) {
                        dataset.getSeries(serieNumber).add(m, parseDouble(tokenizer.nextToken().trim()), true);

最后一行代码,我在 scv 文件的最后一行将 notifyer 设置为 true,否则每次我添加一个新系列时它都会遍历数据集,并且它足以在最后一行执行此操作。

                    } else {
                        tokenizer.nextToken();
                    }
                    serieNumber++;
                }
            } else {
                br.reset();
                while (tokenizer.hasMoreTokens()) {
                    if (dataset.getSeriesCount() > serieNumber) {
                        dataset.getSeries(serieNumber).add(m, parseDouble(tokenizer.nextToken().trim()), false);

                    } else {
                        tokenizer.nextToken();
                    }
                    serieNumber++;
                }
            }
            fileRow = br.readLine();
        }
        br.close();
    } catch (FileNotFoundException ex) {
        printStackTrace(ex);
    } catch (IOException | ParseException ex) {
        printStackTrace(ex);
    }
    return dataset;
}

这也是我在处理从上面的代码调用的 heders 和时间戳时使用的方法。 (有时 csv 文件会遗漏 headers)

/**
 * If the start cahr "#" is missing then the headers will all be "NA".
 *
 * @param fileRow a row with any numbers of headers,
 * @return ArrayList with headers
 */
protected List<String> getHeaders(String fileRow) {
    List<String> returnValue = new ArrayList<>();
    StringTokenizer tokenizer;
    if (fileRow.startsWith("#")) {
        tokenizer = new StringTokenizer(fileRow.substring(1));
    } else {
        tokenizer = new StringTokenizer(fileRow);
        tokenizer.nextToken();
        tokenizer.nextToken();//date and time is one header but two tokens
        while (tokenizer.hasMoreTokens()) {
            returnValue.add("NA");
            tokenizer.nextToken();
        }
        return returnValue;
    }
    tokenizer.nextToken();
    while (tokenizer.hasMoreTokens()) {
        returnValue.add(tokenizer.nextToken().trim());
    }
    return returnValue;
}

/**
 * @param fileRow must match pattern "yyyy-MM-dd HH:mm:ss.SSS"
 * @return
 * @throws ParseException
 */
public Millisecond getMillisecond(String timeStamp) throws ParseException {
    Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(timeStamp);
    return new Millisecond(date);
}

假设您从 doInBackground() 的实现中调用 generateDataSet(),对 dataset 的更改通常会在后台线程上触发事件,这违反了 Swing 的 single thread rule. Instead, publish() interim results and process() them as shown here