【问题标题】:How to read double from file fast in JAVA如何在 JAVA 中快速从文件中读取双精度
【发布时间】:2017-07-21 07:55:26
【问题描述】:

我有很多小文件包含一些数字,像这样。

我需要读取第一个和第二个双打,为此我使用 BufferedReader 读取行并溢出它们,但它非常慢。我想知道是否有其他方法可以更快地做到这一点?

File ifile = new File(dataFile);
FileReader ifr=new FileReader(ifile);
BufferedReader br = new BufferedReader(ifr);
br.readLine();
List<Double> ix = new ArrayList<Double>(1000);
List<Double> iy = new ArrayList<Double>(1000);
for (String sLine = br.readLine(); sLine != null && sLine != ""; sLine = br.readLine()) {
    String[] tmp = sLine.split(" ");
    double x = Double.parseDouble(tmp[0]);
    double y = Double.parseDouble(tmp[1]);
    ix.add(x);
    iy.add(y);
}
br.close();

【问题讨论】:

  • 您是否尝试过分析您的代码?你知道你的代码到底是什么瓶颈吗?

标签: java string io double


【解决方案1】:

请找到代码中提到的java doc。

package com.learning.stackoverflow;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import static com.google.common.base.MoreObjects.firstNonNull;

/**
 * {@link FileReader} accept file name and returns
 * first and second column value per line in the embeded object {@link RequiredData}
 * when <code>getDoubleValuesPerLine()</code> is called
 */
public class FileReader {
    private final String completeFilePath;
    private final List<RequiredData> requiredDataList;

    public FileReader(String completeFilePath) {
        this.completeFilePath = completeFilePath;
        this.requiredDataList = new ArrayList<>();
    }

    /**
     * Method getDoubleValuesPerLine() will return first and
     * second double values in the embeded object {@link RequiredData}
     *
     * @return
     */
    public List<RequiredData> getDoubleValuesPerLine() {
        try (Stream<String> stream = Files.lines(Paths.get(this.completeFilePath))) {
            stream.forEach(this::readDataFromStringLine);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return requiredDataList;
    }

    private void readDataFromStringLine(String stringLine) {
        String[] independentValues = firstNonNull(stringLine.trim(), "").split(" ");
        requiredDataList.add(new RequiredData(Double.valueOf(independentValues[0]), Double.valueOf(independentValues[1])));
    }

    public class RequiredData {
        private final Double firstColumn;
        private final Double secondColumn;

        public RequiredData(Double firstColumn, Double secondColumn) {
            this.firstColumn = firstColumn;
            this.secondColumn = secondColumn;
        }

        public Double getFirstColumn() {
            return firstColumn;
        }

        public Double getSecondColumn() {
            return secondColumn;
        }
    }
}

【讨论】:

  • 如何避开第一行、标题行
  • 能详细说明一下Mark.zxx吗?
【解决方案2】:

这里可能发生的一个小修改是,不是分割整行,而是获取一个数组并从该数组中读取;您可以使用正则表达式来获取最初的两个双精度值。

如果读取的字符串非常大,这可能会提高性能。

...
...
Pattern pattern = Pattern.compile("^([\\d.-]*)\\s([\\d.-]*)");
for (String sLine = br.readLine()) {
    Matcher matcher = pattern.matcher(sLine);
    if (matcher.matches()) {
        double x = Double.parseDouble(matcher.group(1));
        double y = Double.parseDouble(matcher.group(2));
        ix.add(x);
        iy.add(y);
    }
}
...
...

您还可以跳过空行检查和其他验证,因为 if 中的代码仅在模式与该行匹配时才会执行。

这里使用的正则表达式演示:https://regex101.com/r/gqHAWs/1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2016-06-10
    • 1970-01-01
    相关资源
    最近更新 更多