1

There is a text file filled with 1's and 0's. I am trying to load one N_by_M matrix in Java with all data taken from that file. I do not know the dimensions of the matrix ahead of time because it depends on how much data the file has. What is guaranteed is that each line in the file contains the same number of characters. My code snippet works, but I feel awkward about it because:

  1. I am using a BufferedReader instance once only to calculate the number of rows and closing it and creating another instance only because I do not know how to rewind!
  2. I am using the second instance to read the actual data and load to the matrix.
  3. Within a loop, I am finding the column size. I need to find it only once. Yet, it is in a loop, finding it again and again which is redundant.

Please tell me how I could improve it by using BufferedReader only once and how to find the column only once.

    char[][] areas;
    String path = "C:\\test\\data.txt";
    BufferedReader br = new BufferedReader(new FileReader(path));
    String s;
    int numRows=0, numColumns=0;
    while((s = br.readLine()) != null) {
        if(numColumns==0)
            numColumns=s.length();
        numRows++;
    }
    br.close();
    areas = new char[numRows][];
    br = new BufferedReader(new FileReader(path));
    int i=0;
    while((s = br.readLine()) != null) {
        areas[i] = s.toCharArray();
        i++;
    }
    br.close();
softwarelover
  • 1,009
  • 1
  • 10
  • 22

3 Answers3

2

I strongly suggest you start with List<String> lines = Files.readAllLines(Paths.get(path)); Since you then want to read all of the lines as char[]s, you could do something like

List<String> lines = Files.readAllLines(Paths.get(path));
char[][] areas = new char[lines.size()][];
for (int i = 0; i < areas.length; i++) {
    areas[i] = lines.get(i).toCharArray();
}
lines.clear(); // <-- since we wanted areas...
// ...
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

As Jon Skeet points out here, I would not really bother if I had to multipass the file.

If you really want to pass it only once, I would consider reading line by line, storing each of them into a List, and process the list afterwards.

...
LinkedList<String> lines = new LinkedList<String>();
int numRows = 0, numCol = 0;
while((s = br.readLine()) != null) {
  numRows++;

  // Filling list
  lines.addLast(s);
}

int[][] mat = new int[numRows][];

for(int i = 0; i < lines.size(); i++) {
  mat[i] = lines.get(i).toCharArray();
}

lines.clear();
Community
  • 1
  • 1
Markus Weninger
  • 11,931
  • 7
  • 64
  • 137
  • 1
    Thanks. I have taken this out of the while-loop: if(numCol == -1) numCol = s.length(); Once the matrix is constructed, I can simply do this: numCol = areas[0].length; – softwarelover Jan 24 '16 at 01:13
0

Rewind a BufferedReader:

br.mark();
// read some lines
br.reset();
Heri
  • 4,368
  • 1
  • 31
  • 51
  • Not possible for me to use. I do not know what limit to put on the mark since I do not have any knowledge of the amount of data, and number or rows and columns in the file. – softwarelover Jan 24 '16 at 01:06
  • Why not using the file size? Anyway, using a self growing List, as others pointed out, is IMO the best approach. – Heri Jan 24 '16 at 10:54