Search code examples
javastringmatrixinputstreambufferedreader

How to read each char in a line from a text file to a 2d matrix?


I have a text file that looks like this:

abcd
efgh
ijkl

I need to create String[][] resultMatrix = new String[3][4]; to store the values such that each line is a row and each char in a line is an element of that row, but I don't always know the dimensions of the matrix ahead of time.

What I have returns one string, but I need a 3x4 matrix:

public static String[][] readTxt(String filename) throws IOException {
    InputStream file = new FileInputStream(filename);
    BufferedReader buffer = new BufferedReader(new InputStreamReader(file));

    String line = buffer.readLine();
    StringBuilder sb = new StringBuilder();

    line = null;
    while ((line = buffer.readLine()) != null) {
        sb.append(line + "\n");
    }

    String fileString = sb.toString();
    fileString = fileString
            .replaceAll("\r", "")
            .replaceAll("\n>[A-Z]+", ">")
            .replaceAll("[0-9]+\n", "");

    String[] lines = fileString.split(">");
    String[][] resultMatrix = new String[lines.length][lines[0].length()];

    for (int i = 0; i < lines.length; i++) {
        resultMatrix[i] = lines[i].split("");
    }

    buffer.close();
    return resultMatrix;
}

Solution

  • You've made it epically complicated.

    EDIT: Turned collect to list -> list to array into calling toArray on stream directly.

    public static String[][] readTxt(String fn)  throws IOException {
        return Files.lines(Paths.get(fn))
            .map(s -> s.split(""))
            .toArray(String[][]::new);
    }
    

    step by step:

    Files.lines(Paths.get(fn))

    Read the entire fn file in, and process it line-by-line

    .map(s -> s.split(""))

    Turn a String into a String[] by calling .split("") - split splits strings on some delimiter, and if you pass the empty string as delimiter, you end up with each and every character separated out. We now have a stream of string arrays

    .toArray(String[][]::new)

    Turn the stream into an array. This requires telling the toArray method how to construct a new array of the right size. String[][]::new is java-ese for: The concept of invoking new String[X][] given a single int parameter (the size). As in, String[][]::new doesn't create a new array. It represents the concept of creating them (It's a method reference: It represents the idea of writing new String[X][]).