繁体   English   中英

CSV到双数组列表

[英]CSV to list of double arrays

我试图将csv文件的内容放入双数组列表中。 我有一个类型为double []的列表,并想知道如何填充其中的数组。

List <Double[]> lines = new ArrayList<Double[]>(); 

我之前通过执行以下操作为这些数组添加了值

while ((thisLine = br.readLine()) != null){ //while there is a line to read
String newLine = thisLine.replace("station_readings,", "");   //replace station headings with blank
lines.add(newLine.split(",")); 

但这仅在列表由字符串数组组成时才有效。

无论如何,将此csv文件中的内容放入双打数组中。

CSV内容示例:

name,time,frequency,targetPower,power,stateOfCharge
station_readings,2018-04-27T14:04:00.2Z,49932,273.093,294.469,49.2343
station_readings,2018-04-27T14:04:00.3Z,49922,313.299,292.487,49.2269
station_readings,2018-04-27T14:04:00.4Z,49932,273.093,292.235,49.2269

所有建议都赞赏。

提前致谢。

(注意 - 我应该得到一个新的csv,其中日期格式以ms为单位,而不是如何在此处显示,从而使csv中的所有值都为“数字”)

我将流文件中的行,然后拆分每一行并单独流式传输:

List<double[]> lines = 
    Files.lines(Pathes.get("/path/to/file.csv"))
         .skip(1) // Skip the heading
         .map(line -> Arrays.stream(line.split(","))
                            .skip(1) // Skip the "station_readings"
                            .mapToDouble(Double::parseDouble)
                            .toArray()
              )
         .collect(Collectors.toList());

编辑:
@ user7刚刚指出OP正在寻找List<Double[]> 这当然也可以以类似的方式:

List<Double[]> lines = 
    Files.lines(Pathes.get("/path/to/file.csv"))
         .skip(1) // Skip the heading
         .map(line -> Arrays.stream(line.split(","))
                            .skip(1) // Skip the "station_readings"
                            .map(Double::new)
                            .toArray(Double[]::new)
              )
         .collect(Collectors.toList());

如果您的CSV的每一行都有格式

station_readings,2018-04-27T14:04:00.3Z,49922,313.299,292.487,49.2269

前两列的数据无法解析为double

因此,您只能解析剩余的列。

实现此目的的一种方法是将所有行读取到thisLine变量中。

在此之后,您可以拆分分隔符以获取字符串数组:

String[] rowRaw = thisLine.split(",");

然后你可以将它从第3个元素迭代到结尾,将其解析为double并将其放入适当的slzed double[] 然后可以将其添加到您的列表中。

double[] row = new double[rowRaw.length - 2];
for (int i=2; i<rowRaw.length; i++) {
    row[i - 2] = Double.parseDouble(rowRaw[i]);
}

lines.add(row);

如果要将第二列(时间戳字符串)解析为有意义的数字,可以按如下方式进行迭代

double[] row = new double[rowRaw.length - 1];
row[0] = toDouble(rowRaw[1]);
for (int i=2; i<rowRaw.length; i++) {
    row[i - 2] = Double.parseDouble(rowRaw[i]);
}

lines.add(row);

使用一种方法将字符串转换为double(时间戳长存储为double)。 你可能不得不调整它,它没有经过测试。

double toDouble(String tsStr) {
    TimeZone utc = TimeZone.getTimeZone("UTC");
    SimpleDateFormat sdf = new  SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    sdf.setTimeZone(utc);
    Date date = sdf.parse(tsStr);
    return Double.longBitsToDouble(date.getTime());
}

首先,您可能想要使用double[] ,而不是Double[] “Double”和“double”不一样 - 大写版本是一​​个类,这意味着它产生的开销远远超过一个简单的数字,这只是几个字节。

无论哪种方式,您都可以使用Double.parseDouble转换每个CSV字段,但日期字段除外,可以使用Instant.parse进行解析:

String[] fields = thisLine.split(",");

double[] values = new String[fields.length - 1];

Instant dateTime = Instant.parse(fields[1]);
values[0] = dateTime.toEpochMilli();

for (int i = 2; i < fields.length; i++) {
    values[i - 1] = Double.parseDouble[fields[i]);
}

lines.add(values);

您的评论表明,真实的CSV与您共享的示例CSV不同。 在这种情况下,您可以跳过使用Instant:

String[] fields = thisLine.split(",");

double[] values = new String[fields.length - 1];

for (int i = 1; i < fields.length; i++) {
    values[i - 1] = Double.parseDouble[fields[i]);
}

lines.add(values);

但是,作为一个好的设计,你根本不应该使用数组。 您应该定义一个数据类,因此每个double值的含义都是明确的:

import java.time.Instant;
import java.util.Objects;

public class StationReading {
    private final String name;
    private final Instant time;
    private final double frequency;
    private final double targetPower;
    private final double power;
    private final double stateOfCharge;

    public StationReading(String name,
                          Instant time,
                          double frequency,
                          double targetPower,
                          double power,
                          double stateOfCharge) {
        this.name = name;
        this.time = time;
        this.frequency = frequency;
        this.targetPower = targetPower;
        this.power = power;
        this.stateOfCharge = stateOfCharge;
    }

    public String getName() {
        return name;
    }

    public Instant getTime() {
        return time;
    }

    public double getFrequency() {
        return frequency;
    }

    public double getTargetPower() {
        return targetPower;
    }

    public double getPower() {
        return power;
    }

    public double getStateOfCharge() {
        return stateOfCharge;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() +
            "[name=\"" + name + "\"" +
            ", time=" + time +
            ", frequency=" + frequency +
            ", target power=" + targetPower +
            ", power=" + power +
            ", state of charge=" + stateOfCharge +
            "]";
    }

    public static StationReading fromLine(String line) {
        Objects.requireNonNull(line, "Line cannot be null.");

        String[] fields = line.split(",");
        if (fields.length != 6) {
            throw new IllegalArgumentException(
                "Cannot parse a line unless it has exactly six fields.");
        }

        String name = fields[0];

        Instant time = Instant.parse(fields[1]);
        // When you get a new CSV which represents times in milliseconds,
        // change the above to:
        //
        // double ms = Double.parseDouble(fields[1]);
        // Instant time = Instant.ofEpochMilli((long) ms);
        // time = time.plusNanos((long) ((ms - Math.floor(ms)) * 1_000_000));

        double frequency = Double.parseDouble(fields[2]);
        double targetPower = Double.parseDouble(fields[3]);
        double power = Double.parseDouble(fields[4]);
        double stateOfChange = Double.parseDouble(fields[5]);

        return new StationReading(name, time,
            frequency, targetPower, power, stateOfChange);
    }
}

现在,您的读取循环很简单:

List<StationReading> readings = new ArrayList<>();
while ((thisLine = br.readLine()) != null) {
    StationReading reading = StationReading.fromLine(thisLine);
    readings.add(reading);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM