-1

I am reading values in a text file one by one without any problem in Java. The file has integer values as shown below:

2 3
5 6 7 8 9
12 13 15 18 21 26 55
16 24 45 58 97

I need to read just a single line values instead of reading all values and there is an example on How to get line number using scanner, but I am looking a solution without using LineNumberReader and using a counter by looping all lines. Instead, it would be good to get the line number via scanner method that I already use to read values. Is it possible?

Here is the method I try to create:

public static List<Integer> getInput(int lineIndex) throws FileNotFoundException{   
    List list = new ArrayList<Integer>();
    Scanner scan = new Scanner(new File(INPUT_FILE_NAME));
    int lineNum=0;
    //s = new Scanner(new BufferedReader(new FileReader("input.txt")));

    while(scan.hasNextLine()) {         
        if(lineNum == lineIndex) {
               list.add(scan.nextInt()); //but in this case I also loop all values in this line
        }
        lineNum++;      
    }
    scan.close();
    return list;
}
  • When I run the code you posted, I get an infinite loop. Do you? – Abra Jul 12 '20 at 17:19
  • @Abra It is possible because I omitted some parts for brevity. But if you have any idea of course you do not rely on my code. Any help pls? –  Jul 12 '20 at 17:31

2 Answers2

1

If you have a small file, where it is acceptable to load the whole content into memory:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

....

public static List<Integer> getInput(int lineIndex) {
    List<Integer> list = new ArrayList<>();
    try {
        String line = Files.readAllLines(Paths.get("path to your file")).get(lineIndex);
        list = Pattern.compile("\\s+")
                .splitAsStream(line)
                .map(Integer::parseInt)
                .collect(Collectors.toList());
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    return list;
}

The method Files.readAllLines returns a list of all lines of the file as strings, where each string corresponds to one line. with get(lineIndex) you get the desired nth line back and only have to parse the strings to integers.

Second approach:

If you have a large file make use of the lazy evaluation of streams:

public static List<Integer> getInputLargeFile(int lineIndex) {
    List<Integer> list = new ArrayList<>();
    try (Stream<String> lines = Files.lines(Paths.get("path to your file"))) {
        String line = lines.skip(lineIndex).findFirst().get();
        list = Pattern.compile("\\s+")
                .splitAsStream(line)
                .map(Integer::parseInt)
                .collect(Collectors.toList());
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    return list;
}

With this approach you use the method lines.skip to jump n lines from the beginning of the file. And with findFirst().get() you get the next line after your jump. Then do the same as above to convert the numbers.

Eritrean
  • 15,851
  • 3
  • 22
  • 28
  • Thanks for reply, but I am looking a solution that goes to the given index directly by skipping the others. For example if I am concerning 100th line, it must skip all the other lines. –  Jul 12 '20 at 17:44
  • @Jason That is exactly what I'm doing with both aproachs above `...get(lineIndex);` and `lines.skip(lineIndex)...` – Eritrean Jul 12 '20 at 17:47
  • 2
    It appears that the OP does not understand your solution. Perhaps you should add more explanation of how your code works? – Abra Jul 12 '20 at 17:54
  • @Abra Edited. Thanks for your advice. – Eritrean Jul 12 '20 at 18:07
  • @Eritrean Perfect!!! Now it's ok, thanks a lot Abra for warning :) –  Jul 12 '20 at 18:38
0

Not to iterate while reading the number in desired line, maybe you can read the line with scanner.nextLine(), then you can use split("\\s") to get the staring values of integers into an array, then you can simply cast and add them in your list:

public static void main(String[] args) throws FileNotFoundException {
    Scanner scan = new Scanner(new File("input.txt"));
    List<Integer> list = new ArrayList<>();
    int lineNum = 0;
    int lineIndex = 2;

    while(scan.hasNextLine()) {
        if(lineNum == lineIndex) {
            String[] nums = scan.nextLine().split("\\s");
            for (String s : nums){
                list.add(Integer.parseInt(s));
            }
            break;
        }
        lineNum++;
        scan.nextLine();
    }

    System.out.println(list); // [12, 13, 15, 18, 21, 26, 55]
}
Sercan
  • 2,081
  • 2
  • 10
  • 23
  • Thanks, but it gives the first line's values instead of given index. Nevertheless, voted up. –  Jul 12 '20 at 17:12
  • Yes you are right, because even thought we increase loop counter, we did not move scanner next line, so it reads first line when condition is true. We need to add `scan.nextLine()` after iterator, I will edit my answer – Sercan Jul 12 '20 at 17:19
  • I also tried `scan.nextLine()` before your last comment, but it does not solve the problem and causes `scan.hasNextLine()` returns `false`. I am not sure why, but I also think the same approach (skip to the next line). –  Jul 12 '20 at 17:30
  • Strange, I just tried it with your input, and I was able to read any line by changing `lineIndex`. Let me share whole block of code, maybe I am missing something – Sercan Jul 12 '20 at 17:41