Code snippet : comment récupérer les paramètres des nombres décimaux sous windows en Java

Bout de code pour lire les paramètres d’affichage avancés du poste windows en Java.

Code snippet : comment récupérer les paramètres des nombres décimaux sous  windows en Java

Ceci est un bout de code qui permet de lire les préférences du poste utilisateur sous Windows et de trouver les paramètres d'affichage des nombres décimaux.

Évidemment, cela ne fonctionne que sous windows.

Listons d’abord les propriétés systèmes disponibles par défaut :

System.getProperties().forEach(
	(o, o2) -> System.out.printf("Prop : %s / %s\n", o, o2)
);

et vous obtenez :

Liste des propriétés système

Nous voyons que nous accédons facilement à la propriété user.language. Seulement cette propriété donne la langue du poste mais sous windows, il est possible de changer des paramètres avancés tel que les formats des dates ou des nombres décimaux :

Si on veut afficher des nombres décimaux, nous pouvons simplement utiliser les locales default et nous obtenons:

System.out.println("Locale: " + Locale.getDefault().toString());
NumberFormat nf = NumberFormat.getNumberInstance(Locale.getDefault());
DecimalFormat df = (DecimalFormat)nf;
System.out.println("Locale default : " + df.format(123456.789));

et on obtient un résultat qui ne prend pas en compte notre paramétrage du poste :

Du coup si vous souhaitez exporter des nombres décimaux selon la préférence de l’utilisateur, un moyen de faire est d'aller lire ces données via le Kernel32 (cette méthode est très fortement inspirée de ce qui est fait dans IntelliJ)

import com.sun.jna.Native;

(...)

private interface Kernel32 extends com.sun.jna.win32.StdCallLibrary {
        int LOCALE_SDECIMAL = 0x0000000E;
        int LOCALE_STHOUSAND = 0x0000000F;

        int GetLocaleInfoEx(String localeName, int lcType, char[] lcData, int dataSize);
        int GetLastError();
}

static void getNbFormat() {
        Kernel32 kernel32 = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class);
        int bufferSize = 128, rv;
        char[] buffer = new char[bufferSize];

        rv = kernel32.GetLocaleInfoEx(null, Kernel32.LOCALE_SDECIMAL, buffer, bufferSize);
        if (rv < 2) throw new IllegalStateException("GetLocaleInfoEx: " + kernel32.GetLastError());
        System.out.println("Decimal sep: " + new String(buffer, 0, rv - 1));

        rv = kernel32.GetLocaleInfoEx(null, Kernel32.LOCALE_STHOUSAND, buffer, bufferSize);
        if (rv < 2) throw new IllegalStateException("GetLocaleInfoEx: " + kernel32.GetLastError());
        System.out.println("Thousands sep: " + new String(buffer, 0, rv - 1));
}

Il faut surement rajouter dans votre pom.xml :

<dependency>
    <groupId>com.sun.jna</groupId>
    <artifactId>jna</artifactId>
    <version>3.0.9</version>
</dependency>

et vous obtenez

à partir desquelles vous pouvez redéfinir le pattern d'affichage de vos nombres décimaux qui prendra bien en compte les paramètres du poste utilisateur (comme le fait Excel par exemple).

Ressources :

- Cover photo by Bruno Martins