繁体   English   中英

csv转二维双阵列

[英]csv to 2D double array

我正在尝试将 csv 电子表格转换为双二维数组。 我设法将 csv 转换为二维字符串数组。 我现在正试图将其转换为双精度。 我得到一个NumberFormatException我相信这是因为当我尝试Double.parseDouble,它一直在读取 header 列,这是一个字符串。 也可能是我的 csv 中的逗号? 不知道我的下一步是什么。

public class Filetester {
    private String myArray [][] = new String [50][]

public Filetester(String filename) throws IOException {
    File file = new File(filename);
    Scanner s = new Scanner(file);
    String delimiter = ",";
    int count = 0;
    s.nextLine();
    while (s.hasNextLine()) {
        count++;
        String line = s.nextLine();
        //System.out.println(line);
        String[] arrayAsString = line.split("\\s*" + delimiter + "\\s*";
        myArray[count] = arrayAsString;
        double[] arrayAsDouble = new double [arrayAsString.length];
        for (int i = 0; i < arrayAsString.length; i++) {
            arrayAsDouble[i] = Double.parseDouble(arrayAsString[i].replaceAll(",", "");
       }
 }

}

我的 csv 看起来像这样

A, B, C, D 
1.0, 2.0, 3.0, 4.0
13.0, 2.0, 3.0, 4.0
1.0, 2.0, 3.0, 4.0

我认为只是一些建议可能会对您有所帮助,但请记住,对于您的特定应用程序,我不知道您的最终目标是什么。

我看到的是一个 class ( Filetester ),其中包含一个名为myArray[][]的实例成员字符串数组变量。 当您实际寻求实现double[][]数据类型数组时,我不明白为什么您希望这是一个字符串数组。 我建议您声明这是一个 double[][] 类型数组,一旦Filetester class 被实例化,您就可以通过Getter 方法访问该数组。 而且,不要初始化这个变量,现在你不知道在 class 构造器中提供的 CSV 文件中可能包含多少数据。 在实际实例化Filetester class 时执行此操作:

public class Filetester {

    private double[][] csvFileDoubles;
    
    // Contructor
    public Filetester(String filename) {

    }

    // Getter Method
    public double[][] getCSVFileDoubles() {
        return csvFileDoubles;
    }
}

就目前而言,只有在Filetester ZA2F2ED4F8EBC2CBB4C21A29DC40AB4C21A29DC40AB4C21A29DC40AB 的构造函数中提供了表示要处理的 CSV 文件的路径和文件名的字符串时,才能实例化Filetester object将所有代码猛烈撞击到该构造函数中是个好主意。 在构造函数中保持简单易读。 从构造函数调用方法来执行任何任务,例如:

public class Filetester {

    private double[][] csvFileDoubles;  // Default is null.
    
    // Contructor
    public Filetester(String filename) {
        this.csvFileDoubles = getDoublesFromCSV(filename, ",");
    }
    
    public double[][] getCSVFileDoubles() {
        return csvFileDoubles;
    }

    /* Returns a 2D double type Array (double[][]) from the data contained
       within the supplied CSV data file. It is expected that you also supply
       the delimiter used within that supplied CSV file. Any CSV file supplied
       to this method is also expected to contain a Column Names Header Line
       as the very first line of the file.                               */
    private double[][] getDoublesFromCSV(String csvFilePath, String delimiter) {

    }

}

你会在这里注意到一些事情。 首先,实例成员数组变量csvFileDoublesgetDoublesFromCSV()方法初始化和填充,这仅在实例化Filetester时发生。

其次, csvFileDoubles数组变量和getDoublesFromCSV()方法都被声明为私有,这意味着获取csvFileDoubles数组内容的唯一方法是调用声明为公共getCSVFileDoubles() Getter 方法和getDoublesFromCSV()方法只能通过Filetester class 构造函数调用。

getDoublesFromCSV()方法是Filetester class(到目前为止)的实际工作。 它是检索您想要的 CSV 数据并以精度数据类型数组返回的内容。 稍后您很可能会在此 class 中使用其他方法来完成同样多的工作。 我建议您阅读该方法中的所有评论。 下面是整个Filetester class 的样子:

public class Filetester {

    private double[][] csvFileDoubles;  // Default is null.
    
    // Contructor
    public Filetester(String filename) {
        this.csvFileDoubles = getDoublesFromCSV(filename, ",");
    }
    
    public double[][] getCSVFileDoubles() {
        return csvFileDoubles;
    }

    /* Returns a 2D double type Array (double[][]) from the data contained
       within the supplied CSV data file. It is expected that you also supply
       the delimiter used within that supplied CSV file. Any CSV file supplied
       to this method is also expected to contain a Column Names Header Line. */
    private double[][] getDoublesFromCSV(String csvFilePath, String delimiter) {
        /* A list collection can grow dynamically so it really 
           doesn't matter how many data lines are contained
           within the CSV file. You don't need to worry about
           it.                                              */
        java.util.List<Double[]> doublesList= new java.util.ArrayList<>(); 
        
        // 'Try With Resources' use here so to auto-close reader when done.
        try (java.util.Scanner reader = new java.util.Scanner(new java.io.File(csvFilePath))) {
            /* Read the header line before processing the data lines.
               In this case, we want to ignore it.                 */
            String line = reader.nextLine();  

            // Read through all the other CSV file data lines...
            while (reader.hasNextLine()) {
                line = reader.nextLine();   // Sequencially, read in a line
                if (line.trim().isEmpty()) {
                    // If for some reason the line read is blank then ignore it.
                    continue;
                }
                // Split the read line into columnar parts based on the supplied delimiter.
                String[] lineParts = line.split("\\s*" + delimiter + "\\s*");
                /* Convert the numerical string value in each column of 
                   the read in line into an element of a 'Double' data 
                   type array so to prep for addition to the List.                */
                Double[] linePartsAsDouble = new Double[lineParts.length];
                for (int i = 0; i < lineParts.length; i++) {
                    /* Confirm the column data is actually a String representation
                       of a numerical value so as to prevent the possibility of a
                       'NumberFormatException'. We use the String#matches() method
                       for this with a small Regular Expression (regex). If confir-
                       mation fails then (for this demo) we're going to make it -1.0.
                       Use whatever you like here. The regex used ensures that a string
                       representation of either a signed or unsigned integer or 
                       floating point numerical value was supplied.             */
                    if (!lineParts[i].matches("-?\\d+(\\.\\d+)?")) {
                        lineParts[i] = "-1.0";
                    }
                    linePartsAsDouble[i] = Double.parseDouble(lineParts[i]);
                }
                // Add the created Double[] data type array into the List/
                doublesList.add(linePartsAsDouble);
                
                // Go and read in next line (if there is one)...
            }
        }
        catch (java.io.FileNotFoundException ex) {
            // Display the 'FileNotFoundException' and returns null.
            System.err.println("getDoublesFromCSV() Method Error!");
            System.err.println(ex.getMessage());
            return null;
        }
        
        /* All is good so far so convert List<Double[]> to a primitive
           double[][] type array and return it.                     */
        double[][] dblArray = new double[doublesList.size()][];
        for (int i = 0; i < doublesList.size(); i++) {
            for (int j = 0; j < doublesList.get(i).length; j++) {
                // Streams (Java 8+) is used here to convert from Double to double.
                dblArray[i] = java.util.stream.Stream.of(doublesList.get(i))
                                .mapToDouble(Double::doubleValue).toArray();
            }
        }
        return dblArray;  
    }
}

而且,这里是你可以如何使用这个Filetester class:

public class DemoApp {
 
    public static void main(String[] args) {
        /* Create an instance of Filetester. Supply the full
           path and file name to the Constructor. If you just
           supply the file name as shown below then that file 
           must be contained within the root of your app's 
           Project directory.                             */
        Filetester test = new Filetester("DoublesData.csv");
        
        /* call the Filetester.getCSVFileDoubles() getter
           method to retrieve the generated 2D double[][]
           array.                                       */           
        double[][] dblArray = test.getCSVFileDoubles();
        
        // Display the contents of the 2D Array (dblArray[][])
        for (int i = 0; i < dblArray.length; i++) {
            System.out.println(java.util.Arrays.toString(dblArray[i]));
        }
    }
}

使用您提供的示例浮点文件数据,如果您创建一个名为DemoApp的项目并在其中包含上述两个类,并将示例数据放入项目根目录中名为DoublesData.csv的文件中,那么您会看到以下内容运行应用程序时,控制台 window 中的结果:

[1.0, 2.0, 3.0, 4.0]
[13.0, 2.0, 3.0, 4.0]
[1.0, 2.0, 3.0, 4.0]

暂无
暂无

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

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