Home > Mobile >  How to read a text file into a fixed size String array
How to read a text file into a fixed size String array

Time:09-16

I have created a public array of type String with a size of 30000.

I need to populate the array with the entries from the text file line by line. The txt file just has a new word on each line.

I can accomplish this with an ArrayList but I have to use an array.

Here is my code so far:

public static String[] arrayin = new String[30000];

public static void CreateDict(String filepath) {
    Scanner scanner = new Scanner(filepath);
    for(int i = 0; i < arrayin.length; i  ) {
        arrayin[i] = scanner.next();
    }
    System.out.println(arrayin);
}

The error I am getting:

Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1478)
at CreateDictionary.CreateDict(CreateDictionary.java:27)
at CreateDictionary.main(CreateDictionary.java:13)

CodePudding user response:

Your preconditions are tiresome (in that they are quite silly, you would never do this in a real project so the didactic value of this exercise is highly dubious. If you are in a position to switch the source of this education, for example, if this is a tutorial or book and you can find / buy another one, consider doing so).

The problem you're running into is that you're looping exactly 30,000 times and your code therefore crashes if there are fewer than 30,000 tokens in your stream.

Two points:

  1. Is .next() really what you want?

next() will return 'the next token'. Out of the box, scanner considered any amount of whitespace as 'the stuff between tokens', and therefore the rest as tokens. e.g. if the first line is foo bar, that would be two tokens. If that's what you want, fantastic. If you wanted foo bar in its entirety to be a single token (e.g. because each entry in your string array should contain one entire line), then first fix the scanner to register that you consider 'one newline' to be 'the stuff between tokens' instead of 'any amount of whitespace'. To do this, simply run scanner.useDelimiter("\\R"). \\R is java-ese for: One newline.

  1. Loop until you run out of lines, not 'exactly 30k times'.

Simply loop forever until the scanner has nothing more to give:

int index = 0;
while (scanner.hasNext()) {
    arrayin[index  ] = scanner.next();
}

This will crash if there are more than 30k tokens (the array'd be too small). This sounds like what you wanted; if you just want the code to silently ignore any tokens beyond the 30,000th, you'd have to add (using &&) a second condition that index is below 30k. Otherwise, it stops when the file runs out, leaving all remaining slots in your 30k-sized string array as null pointers.

CodePudding user response:

public static String[] arrayin;

public static void CreateDict(String filepath) {
    Path path = Paths.get(filepath);
    arrayin = Files.lines(path, Charset.defaultCharset())
        //.limit(30_000)
        .toArray(String[]::new);
    System.out.println(Arrays.toString(arrayin));
}

This is a Stream<String> solution. It is a expressive, more declarative way of programming, which can in complexer cases nicely optimize, even parallelize things.

This places every line in the array (without line break). As opposed to your code not every word on every line. And it sizes the array to the number of lines in the file. One may limit the array as per out.commented statement.

Your problem was not using hasNext() when the file has less than 30000 words. Alternatively hasNextLine() and nextLine()

  • Related