Newsgroup: it.comp.java
Titolo: Encoding caratteri e XML... non ci capisco nulla! :-(

Ragazzi scusatemi ma mi rendo conto che ho dei buchi concettuali enormi che
mi portano forse a sopravvaluatere alcuni problemi... nel caso specifico
sono completamente all'oscuro di cosa siano (proprio all'oscuro no ma
quasi), quali siano, come siano fatti, come e quando si usino i vari
standard di encoding dei caratteri...
Il prblema mi si è posto quando sono andato a memorizzare una stringa come
valore di un textNode in una struttura dom. Quando salvo il file (uso un
transformer), il file generato ha codifica UTF-8, e tutti i caratteri
accentati vengono salvati in modo scorretto, tantopiù che poi il file non
viene più riaperto e mi vengono tirate una valanga di eccezioni (succede
anche, ad esempio, che il codice carattere scorretto generato si "mangia"
anche uno o due caratteri seguenti e, se il carattere accentato è alla fine
della stringa, il tag di chiusura elemento viene "mutilato" e tutto va in
malora.
Se specifico tra le autputProperties del trasformer che l'encoding è UTF-16,
l'header del file xml viene cambianto (UTF-16, appunto), ma al codifica
usata è sempre UTF-(, tantopiù che molti parser non riesono più ad aprire il
file, mentre xmlSpy mi avverte che l'header è sbagliato e lo corregge in
UTF-8.
Ora, non sapendo niente sull'argomento, mi chiedo, oltre che "come", "cosa"
devo fare. La cosa migliore sarebbe poter usare un encoding che supporta
tutti i caratteri più diffusi (diciamo gli stessi supportati dalle stringhe
in java), ma non so nè se sia possibile, nè come fare.
Oppure potrei farmi un metodo apposito che sostituisce tutti i caratteri
della stringa con caratteri compatibili UTF-8, ma non so quali sono...
Insomma, vi chiedo qualche linea guida a riguardo
Grazie a tutti
Giacomo

Giacomo Ciani ha scritto:
 > sono completamente all'oscuro di cosa siano (proprio all'oscuro no ma
 > quasi), quali siano, come siano fatti, come e quando si usino i vari
 > standard di encoding dei caratteri...
Una distinzione utile per capire meglio queste faccende, anche se non
ancora la piu' precisa in assoluto, e' quella fra character set ed
encoding. Detto in soldoni, un character set e' proprio quello che il
nome dice, cioe' la collezione dei caratteri disponibili ad un sistema
che usa quel set (ad esempio, un sistema che usa l'ASCII disporrà dei
caratteri
[spazio] ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
A B C D E F G H J K L M N O P R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f
g h i j k l m n o p q r s t u v w x y z { | } ~
senza contare i non-printables); i caratteri sono ordinati, in modo tale
che possa essere definito un mapping fra i caratteri stessi e i numeri
corrispondenti alla loro posizione (ad esempio, 'A' = 65). Un encoding
e' la 'traduzione' di tali numeri in bytes effettivi, cioe' in qualcosa
di direttamente comprensibile per la macchina. Per l'ASCII e per i vari
ISO 8859 la rappresentazione in bytes e' immediata; non e' cosi' per i
set di piu' di 256 caratteri.
Lo standard ISO/IEC 10646, di cui Unicode e' oggi sostanzialmente un
sottoinsieme, prevede posizioni per 2^31 caratteri. UCS-4, UTF-8
(possono codificare tutti i caratteri del set), UCS-2 (può codificare i
primi 65536 caratteri del set, il cosiddetto BMP, Basic Multilingual
Plane) e UTF-16 (può codificare i primi 16 planes del set) sono tutti
encoding di questo character set. UCS-4 usa quattro bytes per ogni
carattere. Si tratta naturalmente di uno spreco di bytes nel caso ad
esempio di un testo composto per intero o prevalentemente da caratteri
ASCII: a questo scopo viene utile UTF-8, che usa un byte per i caratteri
ASCII e da due a sei byte per gli altri (da notare che un testo ASCII
risulta di conseguenza un valido testo UTF-8, e dunque anche Unicode e
ISO/IEC 10646). UCS-2 utilizza ovviamente due bytes. UTF-16 estende
UCS-2 in modo che, con sistemi analoghi a quelli di UTF-8, risulti
possibile 'indirizzare' un numero maggiore di caratteri rispetto al BMP.
Un parser XML deve supportare sia UTF-8 sia UTF-16. Per i tuoi caratteri 
accentati puoi usare uno dei due (UTF-8 risulterà piu' compatto). Puoi 
usare anche l'ISO 8859/1 (8859_1), se il parser lo supporta, e perfino 
l'ASCII (US-ASCII: il carattere verra' rappresentato come entity). Ad 
esempio, il carattere 'à' risultera' come C3A0 (hex) in UTF-8, 00E0 in 
UTF-16, E0 in ISO 8859/1, &#224; (entity) in US-ASCII. Tieni pero' 
presente che, settando la output property relativa all'encoding sul 
Transformer, determini solo la XML declaration: lo stream che scrive su 
file utilizza, come e' normale, l'encoding di default, che ad esempio su 
Linux e' ISO 8859/1. Per controllare l'encoding dell'output puoi usare 
codice simile al seguente (nota in particolare la riga che istanzia 
l'OutputStreamWriter):
//---
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
public class Encodings
{
   public static void main(String[] args) throws Exception
   {
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     DocumentBuilder db = dbf.newDocumentBuilder();
     Document d = db.newDocument();
     Element root = d.createElement("root");
     d.appendChild(root);
     Element child = d.createElement("child");
     root.appendChild(child);
     Text text = d.createTextNode("à");
     child.appendChild(text);
     TransformerFactory tf = TransformerFactory.newInstance();
     Transformer t = tf.newTransformer();
     t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
     DOMSource ds = new DOMSource(d);
     FileOutputStream fos = new FileOutputStream("encodings.xml");
     OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
     StreamResult sr = new StreamResult(osw);
     t.transform(ds, sr);
     FileInputStream fis = new FileInputStream("encodings.xml");
     d = db.parse(fis);
     String s = d.getDocumentElement().getFirstChild().getFirstChild()
              .getNodeValue();
     System.out.println(s);
   }
}
//---
Va da se' che, se usi un editor per visualizzare un file scritto ad 
esempio in UTF-8, esso deve supportare tale encoding, altrimenti vedi 
solo robaccia.
Ciao,
Alberto
---
do...@mclink.it
---
JavaClass - Formazione Java e XML
java...@javaclass.it
http://www.javaclass.it

Grazie, sei stato davvero gentilissimo: adesso non solo ho un pochino più
chiaro il discorso, ma ho anche risolto in pieno il mio problema specifico!
Il codice da te postto funziona alla perfezione!
Grazie
Giacomo