Search code examples
javalistjava.util.scanner

How to convert scanner to String or List


I have a scanner with many lines of text(representing number) and I want to convert all the text in the scanner to a List. Example:

Scanner myScanner = new Scanner(new File("input.txt"));

input.txt:

000110100110
010101110111
111100101011
101101001101
011011111110
011100011001
110010011100
000001011100
101110100110
010001011100
011111001010
100111100101
111111000010

My first thought was to convert it to a String by changing the delimiter to something I know is not in the file:

myScanner.useDelimiter("impossible String");
String content = myScanner.next();

and then use

List<String> fullInput = Arrays.asList(content.split("\n"));

However, it gives me problems later on with parsing the numbers on the scanner. I've tried debugging it but I can't seem to understand the problem. For example, I made it print the String to the console before parsing it. It would print a proper number(asString) and then give me NumberFormatException when it is supposed to parse.

Here's the runnable code:

public static void main(String[] args) throws FileNotFoundException {
        Scanner myScanner = new Scanner(new File("input.txt"));
        myScanner.useDelimiter("impossible String");
        String content = myScanner.next();
        List<String> fullInput = Arrays.asList(content.split("\n"));
        System.out.println(fullInput.get(1));
        System.out.println(Long.parseLong(fullInput.get(1)));
    }

This is what I ended up using after the first didn't work:

Scanner myScanner = new Scanner(new File("input.txt"));
List<String> fullInput = new ArrayList<>();
while (sc.hasNextLine())
    fullInput.add(myScanner.nextLine());

Do you know what's wrong with the first method or is there a better way to do this?


Solution

  • For what you are trying to do here, Scanner is the wrong solution.

    If your goal is to simply read the all lines of the file as String[] you can use the Files.readAllLines(Path, Charset) method (javadoc) to do this. You could then wrap that as a List using Arrays.asList(...).

    What you are actually doing could work under some circumstances. But one possible problem is that String.split("\n") only works on systems where the line terminator is a single NL character. On Windows, the line terminator is a CR NL sequence. And in that case, String.split("\n") will leave a CR at the end of all but the last string / line. That would be sufficient to cause Long.parseLong(...) to throw a NumberFormatException. (The parseXxx methods do not tolerate extraneous characters such as whitespace in the argument.)

    A possible solution to the extraneous whitespace problem is to trim the string; e.g.

      System.out.println(Long.parseLong(fullInput.get(1).trim()));
    

    The trim() method (javadoc) returns a string with any leading and/or trailing whitespace removed.

    But there is another way to deal with this. If you don't care whether each number in the input file is on a separate line, you could do something like this:

      Scanner myScanner = new Scanner(new File("input.txt"));
      List<Long> numbers = new ArrayList<>();
      while (myScanner.hasNextLong()) {
          numbers.append(myScanner.nextLong());
      }
    

    Finally, @ChengThao makes a valid point. It looks like these are binary numbers. If they are in fact binary, then it makes more sense to parse them using Long.parseLong(string, radix) with a radix value of 2. However if you parse them as decimal using parseLong (as you are currently doing) the values in your question will fit into a long type.