0

I have a text file

0.4658 0 3
0.4095 0 3
0.4594 0 3
0.4297 0 3
0.3963 0 3
0.4232 0 3
0.4633 0 3
0.5384 0 3
0.5042 0 3
0.4328 0 3

that I want to read into a 2D double array that looks like this.

{{0.4658, 0, 3},
 {0.4095, 0, 3},
    ... (and so on)
 {0.4328, 0, 3}}

I have the following code:

public static void main(String[] args) throws Exception{
    double[][] ref = null;

    ref = matrix("data80.in",10,3);

 }

public static double[][] matrix(String filename, int size1, int size2) throws Exception {
    double[][] matrix = null;

    BufferedReader buffer = new BufferedReader(new FileReader(filename));

    String line;
    int row = 0;

    while ((line = buffer.readLine()) != null) {
        String[] vals = line.trim().split("\\s+");


        if (matrix == null) {
            matrix = new double[size1][size2];
        }

        for (int col = 0; col < size1; col++) {
            matrix[row][col] = Double.parseDouble(vals[col]);
        }

        row++;
    }
    buffer.close();
    return matrix;
}

But it keeps giving me an outOfBounds exception, and I don't know where I am going wrong. Please help. If anyone has more efficient solutions as well to my problem it would be helpful

John Doe
  • 3
  • 1

3 Answers3

0

You have defined you 2d matrix as

matrix = new double[size1][size2];

meaning there are size1 rows and size2 columns but in following line:

for (int col = 0; col < size1; col++) {

you have used size1. So correction is:

for (int col = 0; col < size2; col++) {
Sumeet
  • 8,086
  • 3
  • 25
  • 45
0

It's because of the following for loop:

for (int col = 0; col < size1; col++) {
   matrix[row][col] = Double.parseDouble(vals[col]);
}

We are using size1 whereas we should be using size2, following would work:

for (int col = 0; col < size2; col++) {
   matrix[row][col] = Double.parseDouble(vals[col]);
}

Also, there is no need for null check inside the for loop, you can remove it and initialise the array in the beginning, e.g.:

public static double[][] matrix(String filename, int size1, int size2) throws Exception {
    double[][] matrix = new double[size1][size2];;

    BufferedReader buffer = new BufferedReader(new FileReader(filename));

    String line;
    int row = 0;

    while ((line = buffer.readLine()) != null) {
        String[] vals = line.trim().split("\\s+");


        for (int col = 0; col < size2; col++) {
            matrix[row][col] = Double.parseDouble(vals[col]);
        }

        row++;
    }
    buffer.close();
    return matrix;
}
Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102
0

Here is yet another concept as to how you can place the delimited numerical data contained within a text file of any number of rows and any number of columns into a Double data type Two Dimensional Array. All you need to do is pass the path and file name to the method. You can also optionally supply the delimiter used within the file, the method default is a comma (,) delimiter since it is one of the most commonly used. Here is the method:

public static double[][] matrix(String filename, String... delimiterInFile) {
    String delimiter = ","; // Default data delimiter in file.
    // See if a optional data delimiter is supplied...
    if (delimiterInFile.length > 0) { delimiter = delimiterInFile[0]; }

    // Catch IO Exceptions
    try {
        //Place the contents of file into a ArrayList
        List<String> list = Files.lines(Paths.get(filename)).collect(Collectors.toList());

        // Get the greatest number of delimited columns contiained 
        // within the ArrayList the whole while ignoring blank lines
        // (there could be blank lines in file). Our columns for our
        // double 2D Array will be determined from this value. We also 
        // determine the true number of rows required (remember, no
        // blank elements allowed so ArrayList.size() wont be good enough).
        int r = 0, c = 0;
        for (int i = 0; i < list.size(); i++) {
            if (!list.get(i).equals("")) {
                int l = list.get(i).split(delimiter).length;
                if (l > c) { c = l; }
                r++;
            }
        }

        // If we have nothing then the get outta here 
        // by returning null.
        if (r == 0 || c == 0) { return null; }

        // Declare and initialize a double data type 2D Array
        double[][] array = new double[r][c];

        // Fill the double type array...
        for (int i = 0; i < list.size(); i++) {
            if (!list.get(i).equals("")) {
                String[] data = list.get(i).split(delimiter);
                for (int j = 0; j < data.length; j++) {
                    array[i][j] = Double.parseDouble(data[j]);
                }
            }
        }
        return array;
    } catch (IOException ex) { 
        // Do what you want with the Exception...
        ex.printStackTrace();
        return null;
    }
}

This method will automatically determine the required number of Rows and Columns for the returned Double data type 2D Array. The method ignores blank file lines so the required Rows needed for the returned Double 2D Array is determined with this in mind. The number of Columns value is determined by iterating through the data lines and detecting which data line contains the most delimited data. That column count is used for the entire 2D Array. This means then that file data lines which contain less columns will have their remaining Array Elements filled with a 0.0 double type value.

The optional delimiter that can be passed to this method can be any string or a RegEx (Regular Expression) string, for example: " " or "\\s+" or "," or ", " or "\t", etc.

This method will also throw an IO Exception should there be a problem accessing the supplied data file.

With the data file schema you provided:

0.4658 0 3
0.4095 0 3
0.4594 0 3
0.4297 0 3
0.3963 0 3
0.4232 0 3
0.4633 0 3
0.5384 0 3
0.5042 0 3
0.4328 0 3

and let's assume this file is named data.txt which is in your classpath, you might use this method like this:

double[][] myData = matrix("data.txt", "\\s+");
for (int i = 0; i < myData.length; i++) {
    String strg = "";
    for (int j = 0; j < myData[0].length; j++) {
         strg+= myData[i][j] + " ";
    }
    System.out.println(strg);
}

Keep in mind, this is not a method I would recommend for really large data files (Hundreds of thousands of lines).

Community
  • 1
  • 1
DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22