Java set locale permanently

462 Views Asked by At

I am completely new to Java (I am mainly using Python) and I am using it on a Windows machine with the IntelliJIDEA IDE. When entering a decimal using the dot (".") instead of the comma (",") separator, I get an error.

Quick googling suggests this has to do with the Locale, which may be changed, e.g. to "en-US". I am not familiar with the Locale at all, but I tried changing it via Locale.setDefault inside the main method. However, the modification apparently is not permanent (when I remove that line and restart the script, the error when entering e.g. "2.5" instead of "2,5" still appears).

How do I permanently change the Locale (I don't want to include some code line for every script I write)? If there is some other way to permanently set "." as the default decimal separator, that's fine too. I'd like to avoid overriding the Windows Region & Language settings. Path variables or the like would be ok. Thanks in advance!


Minimal reproducible example:

import java.util.Scanner;
public class DecimalError {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter decimal number: ");
        double decimal = scanner.nextDouble();
    }

}

Error message:

C:\Users\XYZ\.jdks\openjdk-20.0.1\bin\java.exe "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.1.2\lib\idea_rt.jar=61309:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.1.2\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath "D:\Dokumente\Programming\Java for Absolute Beginners\HelloWorld\out\production\HelloWorld" DecimalError
Enter decimal number: 2.5
Exception in thread "main" java.util.InputMismatchException
    at java.base/java.util.Scanner.throwFor(Scanner.java:947)
    at java.base/java.util.Scanner.next(Scanner.java:1602)
    at java.base/java.util.Scanner.nextDouble(Scanner.java:2573)
    at DecimalError.main(DecimalError.java:8)

Process finished with exit code 1

Successful execution:

C:\Users\XYZ\.jdks\openjdk-20.0.1\bin\java.exe "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.1.2\lib\idea_rt.jar=61318:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.1.2\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath "D:\Dokumente\Programming\Java for Absolute Beginners\HelloWorld\out\production\HelloWorld" DecimalError
Enter decimal number: 2,5

Process finished with exit code 0
2

There are 2 best solutions below

3
Morph21 On

I'm not sure how you used Locale.setDefault(), but the only thing it does is change default settings.

So while Scanner initially uses default settings, it only appears while it's created. If you set default after the object was created then it won't have any effect on that.

Here is an example with comments which describes how it works:

public class DecimalScanner {
  public static void main(String[] args) {
    Locale.setDefault(Locale.ENGLISH); // Sets default locale for whole java application and every object that will use it

    Scanner sc = new Scanner(System.in); // Uses default locale as a base in initialization

    sc.nextDouble(); // "." works

    Locale.setDefault(Locale.GERMANY); // Changed default locale but scanner still have settings from creation time

    sc.nextDouble(); // "." works

    sc = new Scanner(System.in); // Created new scanner with current default value (GERMANY)

    sc.nextDouble(); // "," works

    sc.useLocale(Locale.ENGLISH); // Setting locale for scanner to use

    sc.nextDouble(); // "." works

    // Now default locale is still set to GERMANY so new objects will use that
  }
}

You can also set it on vm options in IntelliJ or while running java from command line with a parameter:

java -Duser.country=EN -Duser.language=en
0
k314159 On

If all you want to do is to parse Strings to doubles, using the same format that you would when writing the double in the source file itself, then don't use Scanner. Scanner specifically uses your locale. Use Double.parseDouble instead:

public class NoDecimalError {

    public static void main(String[] args) {
        var reader = new BufferedReader(new InputStreamReader(System.in));

        System.out.print("Enter decimal number: ");
        double decimal = Double.parseDouble(reader.readLine());
    }

}