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]