简体   繁体   English

csv转二维双阵列

[英]csv to 2D double array

I'm trying to convert a csv spreadsheet into a double 2D array.我正在尝试将 csv 电子表格转换为双二维数组。 I have managed to convert the csv into a 2D string array.我设法将 csv 转换为二维字符串数组。 I am now trying to convert that into a double.我现在正试图将其转换为双精度。 I am getting a NumberFormatException I believe this is because when I try to Double.parseDouble, it keeps reading the column header which is a string.我得到一个NumberFormatException我相信这是因为当我尝试Double.parseDouble,它一直在读取 header 列,这是一个字符串。 It may also be the commas in my csv?也可能是我的 csv 中的逗号? Not sure what my next steps are.不知道我的下一步是什么。

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(",", "");
       }
 }

} }

my csv looks like this我的 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

Just a few suggestions I think might help you out here a little but keep in mind, I have no idea what your ultimate goal is with regards to your specific application.我认为只是一些建议可能会对您有所帮助,但请记住,对于您的特定应用程序,我不知道您的最终目标是什么。

What I see is a class ( Filetester ) that contains an instance member String array variable named myArray[][] .我看到的是一个 class ( Filetester ),其中包含一个名为myArray[][]的实例成员字符串数组变量。 I don't understand why you want this to be a String Array when you are actually seeking to achieve a double[][] data type array.当您实际寻求实现double[][]数据类型数组时,我不明白为什么您希望这是一个字符串数组。 I would suggest you declare this a double[][] type array that you can gain access to via a Getter method once the Filetester class has been instantiated .我建议您声明这是一个 double[][] 类型数组,一旦Filetester class 被实例化,您就可以通过Getter 方法访问该数组。 And, don't initialize this variable, right now you have no idea whatsoever how much data may be contained within the supplied CSV file in the class Contructor.而且,不要初始化这个变量,现在你不知道在 class 构造器中提供的 CSV 文件中可能包含多少数据。 Do this when the Filetester class is actually instantiated:在实际实例化Filetester class 时执行此操作:

public class Filetester {

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

    }

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

As it stands, a Filetester object can only be instantiated if a string representing the path and file name of the CSV file to process is provided within its Constructor for the Filetester class and for now this is good enough but I don't think it's a good idea to slam all your code into that Constructor.就目前而言,只有在Filetester ZA2F2ED4F8EBC2CBB4C21A29DC40AB4C21A29DC40AB4C21A29DC40AB 的构造函数中提供了表示要处理的 CSV 文件的路径和文件名的字符串时,才能实例化Filetester object将所有代码猛烈撞击到该构造函数中是个好主意。 Keep things simple and readable in your constructor(s).在构造函数中保持简单易读。 Call a method from the constructor to carry out any tasks, for example:从构造函数调用方法来执行任何任务,例如:

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) {

    }

}

You'll notice a few things here.你会在这里注意到一些事情。 First the instance member array variable csvFileDoubles is getting initialized and filled by the getDoublesFromCSV() method and this only happens when Filetester is instantiated.首先,实例成员数组变量csvFileDoublesgetDoublesFromCSV()方法初始化和填充,这仅在实例化Filetester时发生。

Secondly, both the csvFileDoubles array variable and the getDoublesFromCSV() method are declared as private which means that the only way to get the contents of the csvFileDoubles array is to call the getCSVFileDoubles() Getter method which is declared as public and, the getDoublesFromCSV() method can only be called through the Filetester class Constructor.其次, csvFileDoubles数组变量和getDoublesFromCSV()方法都被声明为私有,这意味着获取csvFileDoubles数组内容的唯一方法是调用声明为公共getCSVFileDoubles() Getter 方法和getDoublesFromCSV()方法只能通过Filetester class 构造函数调用。

The getDoublesFromCSV() method is the actual work-horse for the Filetester class (so far). getDoublesFromCSV()方法是Filetester class(到目前为止)的实际工作。 It is what retrieves the CSV data you want and returns it in a double data type array.它是检索您想要的 CSV 数据并以精度数据类型数组返回的内容。 Later on you will most likely have other methods within this class that will do just as much work.稍后您很可能会在此 class 中使用其他方法来完成同样多的工作。 I suggest you read all the comments within the method.我建议您阅读该方法中的所有评论。 Here is how the entire Filetester class might look like:下面是整个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;  
    }
}

And, here is how you might use this Filetester class:而且,这里是你可以如何使用这个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]));
        }
    }
}

With the example floating point file data you provided, if you create a project named DemoApp and have these two above classes in it and the sample data placed into a file named DoublesData.csv located within the root directory of your project then you see the following result within your console window when the application is run:使用您提供的示例浮点文件数据,如果您创建一个名为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