Home > Blockchain >  Is there a way to use scanner to read in a full string including the spaces, without reading the ful
Is there a way to use scanner to read in a full string including the spaces, without reading the ful

Time:11-14

Let's say my text file looks like this:

John Doe    18    male
Amy hun     19    female

I need to read this into an array like so

while(reader.hasNextLine()){

    result[i] = new Person(reader.next(),reader.next(),reader.next());
    reader.nextLine();
    i  ;
}

but it keeps messing up my array because it treats each space as a delimiter and does not use it, where the columns are separated by whitespace.

I tried using delimiter to spaces on my scanner but I get the error: Exception in thread "main" java.util.NoSuchElementException. Tried a few things but no luck too. I also can't just read in both names as separate Strings because some rows will only have one name.

CodePudding user response:

You will want to read each line of text, and then parse the line using regex or "regular expressions". The regex is a flexible way of grabbing parts of Strings that match certain rules. For instance, if you iterate through the file line by line, grabbing each line with reader.nextLine():

while (reader.hasNextLine()) {
    String line = reader.nextLine();
    // ...
}

now line holds an line from the file, such as "John Doe 18 male"

Then you will want to split this line into 3 substrings representing the name, age, and sex, and they are represented by text followed by a number followed by text, all split by white space (spaces)

If you call .split(...) on the String, you can use a regex that will divide the String based on these rules:

String regex = "(?<=\\d)\\s |\\s (?=\\d)";

This works because the regular expression, "(?<=\\d)\\s |\\s (?=\\d)" splits at a number followed by white-space: (?<=\\d)\\s or white-space followed by a number: \\s (?=\\d) using regex look-ahead and look-behind rules.

This will split the string into the tokens: {"John Doe", "18", "male"}

The whole thing could look like:

List<Person> personList = new ArrayList<>();

String regex = "(?<=\\d)\\s |\\s (?=\\d)";

while (reader.hasNextLine()) {
    String line = reader.nextLine();
    String[] tokens = line.split(regex);
    Person person = new Person(tokens[0], tokens[1], tokens[2]);
    // or perhaps:
    // Person person = new Person(tokens[0], Integer.parseInt(tokens[1]), tokens[2]);
    personList.add(person);
}

CodePudding user response:

Set your Scanner's delimiter appropriately:

reader.useDelimiter("(?m)(?<=\\d)\\s |\\s (?=\\d)|\n");

With this, you can use your code as-is.


Some test code:

record Person (String name, String age, String gender) {}

public static void main(String[] args) {
    String input ="John Doe    18    male\nAmy hun     19    female\n";
    Scanner reader = new Scanner(input).useDelimiter("(?m)(?<=\\d)\\s |\\s (?=\\d)|\n");
    Person[] result = new Person[10];
    int i = 0;
    while (reader.hasNext()) {
        result[i  ] = new Person(reader.next(), reader.next(), reader.next());
    }
    Arrays.stream(result).filter(Objects::nonNull).forEach(System.out::println);
}

Output:

Person[name=John Doe, age=18, gender=male]
Person[name=Amy hun, age=19, gender=female]
  • Related