BUG carattere "İ" (unıcode U+0130) String.toLowerCase(Locale.ROOT)

51 vues
Accéder directement au premier message non lu

Francesco Zambon

non lue,
22 févr. 2022, 09:20:5622/02/2022
à JUG Padova
Cıao a tuttı,

il seguente programma:

package dummycharset;

import java.util.Locale;

public class Main3 {

        public static void main(String[] args) {
               
                Locale.setDefault(new Locale.Builder().setLanguageTag("tr-TR").build());

                System.out.println("\u0130".toLowerCase());
                System.out.println("\u0130".toLowerCase().length());
                System.out.println("");
                               
                System.out.println("\u0130".toLowerCase(Locale.ROOT));
                System.out.println("\u0130".toLowerCase(Locale.ROOT).length());
                System.out.println("");
               
                System.out.println("\u0130".toLowerCase().equalsIgnoreCase("\u0130".toLowerCase(Locale.ROOT)));
        }

}


genera il seguente output:
i
1


2

false



convertendo la I maiuscola con il punto, vengono aggiunti dei byte.
byte (esadecimale)
69 CC 87

il 69 è la minuscola italiana.

Ho provato con java8 e java11 per windows 10.
Sto usando il debugger di eclipse ed un editor esadecimale(HxD)

riferimenti:

Un saluto,
Francesco


Francesco Zambon

non lue,
22 févr. 2022, 09:26:4622/02/2022
à JUG Padova
Per favore potete provare anche voi?

Grazie mille,
Francesco

Lucio Benfante

non lue,
24 févr. 2022, 06:37:5224/02/2022
à jugp...@googlegroups.com

Ciao,

io ho provato con OpenJDK 17 (Corretto) ed il comportamento è lo stesso.

Per cercare di capire ho provato a vedere cosa prevede lo standard Unicode. A giudicare da qui il cambio di lunghezza della stringa è possibile e previsto dallo standard:

https://www.unicode.org/versions/Unicode14.0.0/ch05.pdf#G21180

Per quanto riguarda il caso specifico, la regola di conversione dovrebbe essere questa:

0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069;

da qui: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt

più quanto indicato nella parte finale qui: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt

Usando il Locale.ROOT (cioè un locale che "is used as the language/country neutral locale") tali regole non vengono applicate, quindi produce una coppia di unicode units (che è quello che restituisce il metodo length di String).

Riassumendo: è abbastanza normale (e logico, secondo me) che usando Locale diversi si abbiano risultati diversi convertendo a lowercase/uppercase. Nel caso specifico, la regola prevista dallo standard Unicode per quel carattere mi sembra applicata correttamente, quindi non lo definirei un bug. Sicuramente non è un bug il fatto che length restituisca un valore maggiore di 1 per un carattere rappresentato mediante più unicode units.

Prova a dare un'occhiata anche a questo articolo. Non è esattamente la stessa situazione che hai evidenziato tu, ma forse qualcosa chiarisce:

https://garygregory.wordpress.com/2015/11/03/java-lowercase-conversion-turkey/

Ciao

  Lucio


Il 22/02/22 15:26, Francesco Zambon ha scritto:
--
Hai ricevuto questo messaggio perché sei iscritto al gruppo "JUG Padova" di Google Gruppi.
Per annullare l'iscrizione a questo gruppo e non ricevere più le sue email, invia un'email a jugpadova+...@googlegroups.com.
Per visualizzare questa discussione sul Web, visita https://groups.google.com/d/msgid/jugpadova/6652bf1d-f30e-4d05-a306-e32aa099e85dn%40googlegroups.com.

Francesco Zambon

non lue,
28 févr. 2022, 02:42:0328/02/2022
à jugp...@googlegroups.com
Ciao Lucio,

Grazie mille per la risposta.

Mi trovo in questa situazione:
nel mio database MariaDB (COLLATE='utf8_general_ci') sono state salvate delle stringhe utilizzando un'applicazione Java installata su un server in Italia (Locale it-IT).
In seguito la stessa applicazione è stata installata su un server in Turchia (Locale tr-TR).
Se devo confrontare le stringhe utilizzo String.equalsIgnoreCase perché la sua implementazione utilizza la classe Character.toLowerCase / toUpperCase che non dipende dal Locale.

Purtroppo non posso impostare lo stesso Locale per tutte le installazioni.
Avrei voluto che String funzionasse di default senza Locale.

Ciao,
Francesco

Répondre à tous
Répondre à l'auteur
Transférer
0 nouveau message