Search code examples
javafilebufferedreaderlarge-files

Storing contents of file in ArrayList of Integer using BufferedReader


I want to store the contents of a textfile of the following format:

First line contains 2 integers, say n and k,separated by a white space.

The following lines contain n integers (n can be very large) (which I would like to store in an ArrayList)

What I got to understand by searching online about ways of handling files in Java is that BufferedReader is the preferred way when dealing with big input as it is faster(compared with Scanner) and also how to do it. My attempt is the following:

public static void main(String[] args) throws IOException {
        StringBuilder t = new StringBuilder();
        try(BufferedReader br = Files.newBufferedReader(Paths.get("./interview1.txt"))) {
            t.append(br.readLine());
            String[] firstLine = new String[2];
            firstLine = t.toString().split(" ");
            int n = Integer.parseInt(firstLine[0]);
           // System.out.println(n);
            int k = Integer.parseInt(firstLine[1]);
           // System.out.println(k);
            String line;
            List<Integer> list = new ArrayList<>(n);
            while((line = br.readLine()) != null){
                String[] thisLine = line.split(" ");
                for(int i = 0; i < thisLine.length; i++){
                   // System.out.print(thisLine[i] + " ");
                   list.add(Integer.valueOf(thisLine[i]));
                }
            }
        } catch (Exception e) {
            System.err.format("IOException: %s%n", e);
        }

Since I know that the first line contains only 2 numbers, I read the line, convert it into an String array of size 2 and then separate the 2 Integers. All good up until now.

The problem comes next, after entering the while loop. I keep on receiving a java.lang.NumberFormatException (which, as far as I know, means that I tried to convert a String that does not contain a parseable int into an Integer) when trying to add the contents into the list.

Uncommenting the first line in the for loop results in the following output:

3 4 2 1 6 7 1 2 2 3 (extra random 2 towards the end??)

Content of the file currently used:

10 5
3 4 2 1 6 7 1 2 3

What am I doing wrong?


Solution

  • You seem to be able to use java.nio, so I recommend using as many of its features as possible and getting rid of a BufferedReader:

    My example file numbers.txt looks like this:

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

    You can read it and store the numbers in separate List<Integer> for each line in a List<List<Integer>> or just store all the numbers you read in that file in a single List<Integer>. Check the following code and its comments:

    public static void main(String[] args) {
        // provide the path to the file
        Path pathToFile = Paths.get("Y:\\our\\path\\to\\numbers.txt");
        // provide a list of lists of numbers
        List<List<Integer>> numbersInLines = new ArrayList<>();
        // or provide a single list of integers
        List<Integer> allNumbers = new ArrayList<>();
    
        // try reading the file, you may want to check if it exists and is valid before
        try {
            Files.lines(pathToFile).forEach(line -> {
                // provide a list for the numbers of each line
                List<Integer> realNumbers = new ArrayList<>();
                // split the line by an arbitrary amount of whitespaces
                String[] lineElements = line.trim().split("\\s+");
                // convert them to integers and store them in the list of integers
                for (String lineElement : lineElements) {
                    // check if there is an empty String
                    if (!"".equals(lineElement)) {
                        // add it to the list of the current line
                        realNumbers.add(Integer.valueOf(lineElement));
                        // and / or add it to the list of all numbers
                        allNumbers.add(Integer.valueOf(lineElement));
                    }
                }
                // store the list of numbers of the current line in the list of lists
                numbersInLines.add(realNumbers);
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        // print each line list
        numbersInLines.forEach(lineNumbers -> {
            lineNumbers.forEach(System.out::print);
            System.out.println();
        });
    
        // and / or print all the numbers in a single line, separated by a whitespace
        allNumbers.forEach(number -> System.out.print(number + " "));
    }
    

    The output will be this:

    121455165
    2
    34567
    4
    
    6
    7891011121314151617
    1 2 14 55 165 2 3 4 5 6 7 4 6 7 8 9 10 11 12 13 14 15 16 17