I have a .txt file with this content: "17.23;12.1;20.34;88.23523;".
I want to read this file as doubles into an ArrayList. And eventually print the ArrayList (and eventually print the min. and max., but I don't think that will be a problem after solving this).
But I only get the output "[ ]".
What am I doing wrong? I've been struggling with this for embarrassing 15+ hours, browsed here, youtube, course books...
My code:
public static void main(String[] args) throws IOException {
File myFile = new File("text.txt");
Scanner scan = new Scanner(myFile);
ArrayList<Double> aList = new ArrayList<>();
while (scan.hasNextDouble()) {
double nextInput = scan.nextDouble();
if (nextInput != 0) {
break;
}
aList.add(nextInput);
}
System.out.println(alist);
}
You should configure your scanner so it will accept:
; as a delimiter, as a decimal separatorWorking code is:
File myFile = new File("input.txt");
// Swedish locale uses ',' as a decimal separator
Scanner scan = new Scanner(myFile).useDelimiter(";").useLocale(Locale.forLanguageTag("sv-SE"));
ArrayList<Double> aList = new ArrayList<>();
while (scan.hasNextDouble()) {
double nextInput = scan.nextDouble();
aList.add(nextInput);
}
System.out.println(aList);
With output [17.23, 12.1, 20.34, 88.23523]
Scanner works by splitting the input into tokens, where tokens are separated by whitespaces (by default). Since there are no whitespaces in the text, the first/only token is the entire text, and since that text is not a valid double value, hasNextDouble() returns false.
Two ways to fix that:
Change the token separator to ;:
scan.useDelimiter(";");
Read the file with BufferedReader and use split():
String filename = "text.txt";
try (BufferedReader in = Files.newBufferedReader(Paths.get(filename))) {
for (String line; (line = in.readLine()) != null; ) {
String[] tokens = line.split(";");
// code here
}
}
That will now result in the following tokens: 17,23, 12,1, 20,34, 88,23523.
Unfortunately, none of those are valid double values, because they use locale-specific formatting, i.e. the decimal point is a ,, not a ..
Which means that if you kept using Scanner, you can't use hasNextDouble() and nextDouble(), and if you changed to use split(), you can't use Double.parseDouble().
You need to use a NumberFormat to parse locale-specific number formats. Since "Uppgift" looks Swedish, we can use NumberFormat.getInstance(Locale.forLanguageTag("sv-SE")), or simply NumberFormat.getInstance() if your default locale is Sweden.
String filename = "text.txt";
try (BufferedReader in = Files.newBufferedReader(Paths.get(filename))) {
NumberFormat format = NumberFormat.getInstance(Locale.forLanguageTag("sv-SE"));
for (String line; (line = in.readLine()) != null; ) {
List<Double> aList = new ArrayList<>();
for (String token : line.split(";")) {
double value = format.parse(token).doubleValue();
aList.add(value);
}
System.out.println(aList); // Prints: [17.23, 12.1, 20.34, 88.23523]
}
}
Since your file has numbers separated by a semi-colon, you won't be able to read them using scan.hasNextDouble() by default. However, there are so many ways of doing it e.g.
Option-1:
scan.useDelimiter(";")
Note that since your file has the comma instead of the dot as the decimal symbol, you can use a Locale in which it is the default.
scan.useLocale(Locale.FRANCE);
Also, the following code block in your code will cause the loop to be terminated after reading the first number itself as the first number in your file in not equal to zero. Simply remove these lines in order to get the desired result:
if (nextInput != 0) {
break;
}
Option-2:
Read a line, split it on a semi-colon, replace the comma with a dot, parse each element from the resulting array into Double and store the same into aList.
Demo:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
File myFile = new File("file.txt");
Scanner scan = new Scanner(myFile);
List<Double> aList = new ArrayList<>();
while (scan.hasNextLine()) {
String nextInput = scan.nextLine();
String[] arr = nextInput.split(";");
for (String s : arr) {
aList.add(Double.valueOf(s.replace(",", ".")));
}
}
System.out.println(aList);
}
}
Output:
[17.23, 12.1, 20.34, 88.23523]
An alternative to replace comma with dot is to use NumberFormat as shown below:
import java.io.File;
import java.io.FileNotFoundException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException, ParseException {
File myFile = new File("file.txt");
Scanner scan = new Scanner(myFile);
NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
List<Double> aList = new ArrayList<>();
while (scan.hasNextLine()) {
String nextInput = scan.nextLine();
String[] arr = nextInput.split(";");
for (String s : arr) {
aList.add(format.parse(s).doubleValue());
}
}
System.out.println(aList);
}
}