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

51 views
Skip to first unread message

Francesco Zambon

unread,
Feb 22, 2022, 9:20:56 AM2/22/22
to 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

unread,
Feb 22, 2022, 9:26:46 AM2/22/22
to JUG Padova
Per favore potete provare anche voi?

Grazie mille,
Francesco

Lucio Benfante

unread,
Feb 24, 2022, 6:37:52 AM2/24/22
to 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

unread,
Feb 28, 2022, 2:42:03 AM2/28/22
to 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

Reply all
Reply to author
Forward
0 new messages