1. Homepage
  2. Articoli
  3. Video
  4. Bash scripting
  5. Sistema
  6. Tips
  7. News


Da Unicode (UTF-8) a HTML (entity)

» Author: Andrea Ganduglia Date: 2009-06-09 10:17:46 Copyright: (c)2009 Andrea Ganduglia

È abbanza divertente capire come funzionano le cose che usiamo ogni giorno. Prendiamo[1] una stringa ASCII:

"abcde".size
#=> 5

ora sostituiamo la "e" con la "è" accentata e otteniamo una stringa UTF-8:

"abcdè".size
#=> 6

come si vede, la seconda stringa pur avendo lo stesso numero di caratteri della prima "pesa" un byte in più, questo significa che mentre [a,b,c,d,e] sono rappresentati con un byte, per rappresentare la lettera è sono necessari 2 byte.

In pratica, per andare al sodo, UTF-8 utilizza un numero variabile di byte per rappresentare un singolo carattere, seguendo questo schema:

Tbl. 1 ~ Maschera di UTF-8
1° Byte 2° Byte 3° Byte Numero di bits liberi Caratteri rappresentabili
0xxxxxxx 7 127 (0 ~ 127)
110xxxxx 10xxxxxx (5+6)=11 2047 (194 ~ 223)
1110xxxx 10xxxxxx 10xxxxxx (4+6+6)=16 65535 (224 ~ 239)

In vero UTF-8 utilizza i bits che rimangono liberi da questa maschera (che può potenzialmente estendersi fino a 6 bytes per un singolo carattere, ma che viene limitata a 4).

Torniamo alla nostra stringa:

"abcdè".each_byte do |c|
    puts c
end
97
98
99
100
195
168

Quelli che vengono stampati non sono altro che i valori ascii di ogni singolo carattere o meglio di ogni singolo byte, quindi avremo queste corrispondenze:

Tbl 2.
Valore/i ASCII Carattere
97 a
98 b
99 c
100 d
195 e 168 è

Si prenda la tabella di prima e si osservi che abcd occupano un byte e hanno valori inferiori a 128, mentre "è" il cui primo byte ricade nell'intervallo successivo occupa 2 byte.

Ottenere il valore dell'entità HTML

Ora, il carattere è può anche essere espresso in HTML con l'entità numerica è e (magia, magia) questo valore può essere mutuato dalla sequenza di bits liberi usati da UTF-8 (cfr. Tbl. 1), vediamo come.

1. I valori decimali dei byte che compongono è

"è".each_byte do |c|
    puts c
end
195
168

2. In base 2

195.to_s(2)
#=> "11000011"
168.to_s(2)
#=> "10101000"

3. Applichiamo la maschera

110  00011
10  101000

Compongo la sequenza di bits che rappresenta è, ovvero solo i bits liberi:

00011 101000

Se lo facessi con Ruby potrei:

byte_1 = "11000011"
byte_2 = "10101000"

utf8_bits = byte_1[3..7]+byte_2[2..7]
puts utf8_bits
#=> 00011101000

4. Ottengo il valore decimale

puts utf8_bits.to_i(2)
#=> 232

... ops! Esattemente il valore che ci aspettavamo! Ora basta esprimerlo come entità HTML per ottenere il risultato desiderato è!

Automatizzare la cosa

Ora che sappiamo come convertire un carattere UTF-8 sarebbe interessante capire come convertire un'intera stringa. Non è difficile, basta analizzare la stringa byte per byte e capire quale maschera applicare.

Ad esempio: se trovo un byte < 128 posso lasciarlo così come si trova perchè si tratta di un carattere ASCII, se trovo un byte che ha valore compreso tra 194 e 223 so che a quel byte e a quello seguente dovrò applicare la maschera a 2 byte, se ne trovo uno con valore tra 224 e 240 so che a quel byte e ai due seguenti dovrò applicare la maschera a 3 byte e così via. Il valore a cui ci si riferisce è quello decimale del primo byte della sequenza.

Per approfondire


Note al documento

1

Userò in tutto l'articolo Ruby, ma è possibile applicare lo stesso procedimento praticamente con qualsiasi linguaggio.