1

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
bproxauf
  • 1,076
  • 12
  • 23
  • 1
    Since you mention a script, you can pass `-Duser.language=en -Duser.country=US` on the java command line (before any class name or -jar option). See https://stackoverflow.com/questions/8809098/how-do-i-set-the-default-locale-in-the-jvm. – VGR May 30 '23 at 11:33
  • What do you consider a script in Java exactly? Are you not compiling programs? – aled May 30 '23 at 11:36
  • @OHGODSPIDERS Whew. Thank you for catching that in time for me to edit it. – VGR May 30 '23 at 11:38
  • @aled: By script, I just meant the .java file, which I'm from the IntelliJIDEA IDE. – bproxauf May 30 '23 at 11:43
  • @VGR: Since I am running the file from the IntelliJIDEA IDE, I am not sure to which command line I'd pass these parameters. – bproxauf May 30 '23 at 11:45
  • 1
    Just FYI in terminology a .java source file is not called a script. – aled May 30 '23 at 11:49
  • @aled: Fair enough, probably I misreferred to it, as I was used to calling .py code files scripts too. – bproxauf May 30 '23 at 11:51
  • @bproxauf can you post a minimal reproducible example? – Morph21 May 30 '23 at 11:52
  • 1
    You set the Windows Region and Language settings. Because that is what determines the locale Java uses by default. Or you use a script to start Java (every time). – Elliott Frisch May 30 '23 at 11:59
  • @Morph21: I have included the example code as well as successful and unsuccessful program run messages. – bproxauf May 30 '23 at 11:59
  • @bproxauf you can set locale for scanner in this way Scanner sc = new Scanner(System.in).useLocale(Locale.ENGLISH); – Morph21 May 30 '23 at 12:00
  • @ElliottFrisch: Region and Language settings are currently set to German (Germany), but I'd like to not modify these (no idea what else would be affected, keyboard layout, date/time format etc., which I do not want to change globally for my computer). – bproxauf May 30 '23 at 12:01
  • Does this answer your question? [Set java system properties in IntelliJ or Eclipse](https://stackoverflow.com/questions/29454494/set-java-system-properties-in-intellij-or-eclipse) – aled May 30 '23 at 12:02
  • @Morph21: That line would need to be included in every java source file from scratch, instead of changing the locale once and for all. – bproxauf May 30 '23 at 12:03
  • In the question you linked, there is [this answer](https://stackoverflow.com/a/56655305/7525132), which mentions the variable `JAVA_TOOL_OPTIONS`. Is this applicable here? – Izruo May 30 '23 at 12:03
  • If you want to permanently change it, you need to change your Windows locale settings, not Java. – Mark Rotteveel May 30 '23 at 12:04
  • 2
    Scanner is specifically designed and documented to use your locale, as set by your operating system (unless overridden). It seems that what you are asking is how to permanently set your Java locale to be different from your Windows locale. You can do that using the JAVA_TOOL_OPTIONS environment variable, but this could have other consequences in situations where you need to use your German locale. And it seems strange to have two different locales, one for Java, and another for non-Java. – k314159 May 30 '23 at 12:08
  • Do you not want to call method `setDefault` (of class `Locale`) in your code? Things like the "locale" apply to the [JVM](https://en.wikipedia.org/wiki/Java_virtual_machine). The JVM is created when you launch your Java program and ceases to exist when your Java program terminates. Seems to me like `Locale.setDefault` is exactly what you need. – Abra May 30 '23 at 12:12
  • @Izruo, @k314159: Creating the `JAVA_TOOL_OPTIONS` environment variable with `-Duser.language=en -Duser.region=US` works. Editing the IDE file `idea64.exe.vmoptions` via `-Duser.locale=en-US -Duser.language=en - Duser.country=US -Duser.variant=US` does not seem to have any effect. – bproxauf May 30 '23 at 12:15
  • @k314159: I simply think that the "." separator should be the default decimal separator (even if in countries like Germany "," is used). Other settings like date/time formats for my computer I am completely fine with, and I would not like to touch those via the Windows locale settings. – bproxauf May 30 '23 at 12:18
  • The `idea64.exe.vmoptions` affects only the JVM that runs IDEA itself, not the JVMs that run your applications. To change the latter, you need to modify your Run Configurations and add JVM options for every single project. – k314159 May 30 '23 at 12:24
  • @k314159: I have not created any Run Configurations until now. But you are saying these need to be created for every single project again? There is no single configuration for the whole IDEA which applies to all projects? – bproxauf May 30 '23 at 12:26
  • Well, Im not sure if this will work for you but you can create Run Configurations and store it as file and then copypaste to each project of yours. Also you did create run configuration if you at least once clicked run in idea, well idea created one on it's own at least – Morph21 May 31 '23 at 06:54

2 Answers2

0

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
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Morph21
  • 1,111
  • 6
  • 18
  • As I understand it, this is a valid solution for that specific Java source file you created. But I am looking for a cross-source-file solution, so that I do not always need to include that command in every single .java file. – bproxauf May 30 '23 at 12:21
  • Well it should work like it's working without changing locale. Since every user have his/her locale set in pc. They will type the numbers like they would normally so it shouldn't be weird for them. Also if you don't won't to bother with that just get it with scanner as string and parse it to double like k314159 said. Ultimately if you will not set locale in run file then every user will have different one. And if you want it only for you then it shouldn't be a problem to change it for whole pc or just change it for specific jvm version you are using. – Morph21 May 30 '23 at 12:29
  • Ok, seems reasonable. – bproxauf May 30 '23 at 12:33
0

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());
    }

}
k314159
  • 5,051
  • 10
  • 32