Luis Averhoff Luis Averhoff - 7 months ago 6
Java Question

Reading a file with integers that may or may be delineated by spaces

So I have this file that is filled only with integers. I would like to, if possible, be able to read a file that may or may not have spaces delineating each integer.

Here are two visual examples.

The first one are integers that are not delineated by spaces while the second one are.

First Example:

020030090
000907000
900208005
004806500
607000208
003102900
800605007
000309000
030020050


Second Example:

0 3 8 0 12 0 15 16 6 0 4 0 0 0 0 0
0 11 5 0 1 0 0 14 13 0 3 9 12 7 0 0
0 0 0 0 6 0 0 0 0 12 0 14 0 0 0 16
10 16 0 6 2 13 0 0 0 8 7 0 0 0 0 0

3 10 1 0 13 0 0 15 0 9 0 16 5 0 0 0
0 0 16 0 0 0 0 11 14 0 13 12 0 3 0 0
4 0 7 8 0 0 12 9 0 0 0 0 0 0 11 0
0 6 0 0 16 0 0 0 11 5 0 0 15 0 0 2

11 0 0 12 0 0 8 2 0 0 0 1 0 0 14 0
0 7 0 0 0 0 0 0 3 11 0 0 8 16 0 9
0 0 13 0 3 6 0 7 16 0 0 0 0 11 0 0
0 0 0 2 5 0 14 0 15 0 0 4 0 13 7 1

0 0 0 0 0 14 5 0 0 0 16 2 13 0 8 10
14 0 0 0 8 0 9 0 0 0 0 11 0 0 0 0
0 0 6 15 7 1 0 3 12 0 0 13 0 2 5 0
0 0 0 0 0 15 0 12 1 14 0 3 0 6 16 0


Note:

I would also like to add that the second file might not be delineated by the same amount. This means that one integer could have one space after it and another integer could have 10 spaces after it.

What I have tried:

I have tried using the split("\s+") in combination with the replaceAll("", " ") but this not work in the second example because it would have more spaces and thus the split function would not work.

I have tried using replaceAll(" ", "") like this so that they have no spaces at all. Then I converted the string into a char array but that presented problems with integers greater than one digit(would not work with the second example as well).

Code:

public void initializeGrid(int grid[][], String fileName) throws FileNotFoundException, IOException
{
Scanner read = new Scanner(Paths.get(fileName));
int value;

for (int i = 0; i < ROWS; i++)
{
String line = read.nextLine();
String [] numbers = line.trim().split("\\s+");

for (int j = 0; j < COLUMNS; j++)
{
value = Integer.parseInt(numbers[j]);
grid[i][j] = value;
}
}
}

Answer

Following the recommendation of @dnault in the comments above, here's an implementation that uses the Java Collection framework instead of a 2d int array. This approach has an advantage over a 2d array in that the List for each row contains exactly as many entries as needed. Using arrays, if a line has less than COLUMN values, the array will contain zeros for all remaining values.

public List<List<Integer>> readFile(String fileName)
        throws FileNotFoundException, IOException {
    BufferedReader br = Files.newBufferedReader(Paths.get(fileName));
    List<List<Integer>> values = new ArrayList<>();


    for(String line; (line = br.readLine()) != null;){
        String[] splitLine = line.trim().split("\\s+");

        if(splitLine.length < 2)
            values.add(parseSingleDigitValues(splitLine[0].toCharArray()));
        else
            values.add(parseDelimitedValues(splitLine));

    }

    return values;
}

private List<Integer> parseSingleDigitValues(char[] line) {
    List<Integer> values = new ArrayList<>();
    for(char c: line){
        values.add(Integer.parseInt(String.valueOf(c)));
    }
    return values;

}

private List<Integer> parseDelimitedValues(String[] line) {
    List<Integer> values = new ArrayList<>();
    for(String str :line)
        values.add(Integer.parseInt(str));
    return values;
}

The resulting List<List<Integer>> can then be easily converted into a 2D int array using the following method:

private int[][] asArray(List<List<Integer>> lists){
    int s1 = lists.size();
    int s2 = 0;
    for(List<Integer> sublist : lists){
        if(sublist.size() > s2)
            s2 = sublist.size();
    }

    int[][] arr = new int[s1][s2];
    for(int i = 0; i < lists.size(); i++){
        List<Integer> sublist = lists.get(i);
        for(int j = 0; j < sublist.size(); j++){
            arr[i][j] = sublist.get(j);
        }
    }
    return arr;
}

EDIT In the end, if you clearly document your code/api then the burden is on the user to put it into proper use. I recommend you opt for simplicity in your API: Tell the user they must provide a space-delimited file. You can then provide a utility class that will convert a non-delimited file into a space-delimited file.

Comments