1. Présentation▲
Les ordinateurs travaillent avec des bits ou suites d'octets (un octet=8 bits). Les chaînes de caractères, entiers, réels sont donc codées sous forme d'octets. Les ordinateurs utilisent donc un procédé qui consiste à transformer les chaînes de caractères en octets, associé à une technique afin de relire les chaînes d'origine. C'est ce procédé qui est appelé encodage.
Il existe plusieurs encodages qui utilisent plus ou moins le même nombre d'octets, donc de caractères disponibles comme ISO-8859-1,
ASCII, UTF-8...
L'encodage UTF-8 est le plus pratique pour échanger des textes constitués de caractères UNICODE
(standard du consortium Unicode). Ce consortium a pour but de répertorier tous les caractères utilisés dans les différentes langues et d'associer à chacun un code noté sous forme hexadécimal.
L'encodage UTF-8 est compatible avec l'encodage ASCII ce qui est très pratique lors des développements informatiques.
Lors des développements d'applications Java et/ou Java EE, il n'est pas rare de constater de nombreux problèmes d'encodage des applications tant au niveau des messages présents dans un navigateur, que des fichiers de propriétés d'une application ou encore de l'encodage des caractères saisis au clavier. La mise en oeuvre d'une application Java nécessite donc la gestion de plusieurs paramètres. La difficulté est qu'il ne faut pas en oublier un seul sous peine de constater l'affichage de "hiéroglyphes" à la place du caractère souhaité.
2. Les fichiers▲
La première contrainte à vérifier est que tous les fichiers (HTML, JSP, JSPF, XML, XSLT...) de l'application développée soient dans l'encodage souhaité. Pour cela, la plupart des IDE peuvent se paramétrer afin de sélectionner l'encodage. Avec Eclipse, nous pouvons sélectionner l'encodage dans le menu Fenêtre - Préférences - Editeurs - Codage du fichier texte et Types de contenu.
3. Les pages JSP et JSPF▲
Il est nécessaire de déclarer dans chaque page JSP ou JSPF d'entête l'encodage utilisé. Pour cela, il faut utiliser la directive JSP adaptée.
<
jsp
:
directive.page
contentType
=
"text/html;charset=UTF-8"
/>
ou
<%@ page
contentType
=
"text/html;charset=UTF-8"
%>
Il est possible également de centraliser l'encodage dans le fichier de configuration et de déploiement de l'application web.xml du serveur Tomcat.
<jsp-config>
<jsp-property-group>
<description>
Config. de l'encodage des pages JSP</description>
<url-pattern>
*.jsp</url-pattern>
<page-encoding>
UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
4. Les pages HTML/XHTML▲
Il est également important de prévenir le navigateur client de l'encodage qu'il doit utiliser pour afficher la page HTML/XHTML. Cette directive est précisée avec la balise meta et le paramètre content.
Il est également possible de préciser l'encodage d'une feuille de style externe à l'aide de la directive placée en tout début de fichier.
@charset "UTF-8";
5. Les feuilles de style XSL▲
Si des transformations XSLT sont utilisées dans notre application, il est nécessaire de déclarer également explicitement l'encodage dans ces pages.
<
xsl
:
output
method
=
"xml"
omit-xml-declaration
=
"yes"
encoding
=
"UTF-8"
indent
=
"yes"
/>
6. Code Java▲
Du point de vue du code Java, il est possible d'utiliser un filtre qui va forcer le serveur d'applications Java à lire les paramètres de la requête dans l'encodage souhaité et qui va renvoyer les réponses avec le même encodage.
package
application.filters;
import
java.io.IOException;
import
javax.servlet.Filter;
import
javax.servlet.FilterChain;
import
javax.servlet.FilterConfig;
import
javax.servlet.ServletException;
import
javax.servlet.ServletRequest;
import
javax.servlet.ServletResponse;
public
class
EncodingFilter implements
Filter {
public
static
final
String ENCODING =
"encoding"
;
private
String encoding;
public
void
init
(
FilterConfig filterConfig) throws
ServletException
{
this
.encoding =
filterConfig.getInitParameter
(
ENCODING);
}
public
void
doFilter
(
ServletRequest req, ServletResponse resp,
FilterChain filterChain)throws
IOException, ServletException
{
req.setCharacterEncoding
(
encoding);
resp.setContentType
(
"text/html;charset="
+
encoding);
filterChain.doFilter
(
req, resp);
}
public
void
destroy
(
) {}
}
Il est alors possible de déclarer ce filtre au sein du fichier de configuration de l'application web.xml. Les filtres étant exécutés dans l'ordre de déclaration, ce mapping doit être le premier déclaré dans le fichier de configuration.
<filter>
<filter-name>
encodingfilter</filter-name>
<filter-class>
application.filters.EncodingFilter</filter-class>
<init-param>
<param-name>
encoding</param-name>
<param-value>
UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>
encodingfilter</filter-name>
<url-pattern>
/*</url-pattern>
</filter-mapping>
L'encodage peut aussi être géré au sein d'une Servlet générique. Chaque Servlet du projet devra alors ensuite hériter de cette Servlet.
package
application.servlets;
import
java.io.IOException;
import
javax.servlet.ServletConfig;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
abstract
class
EncodingServlet extends
HttpServlet {
public
static
final
String ENCODING =
"encoding"
;
private
String encoding;
public
void
init
(
ServletConfig servletConfig)throws
ServletException
{
this
.encoding =
servletConfig.getInitParameter
(
ENCODING);
}
public
void
doGet
(
HttpServletRequest req, HttpServletResponse resp)
throws
IOException, ServletException
{
req.setCharacterEncoding
(
encoding);
resp.setContentType
(
"text/html;charset="
+
encoding);
}
public
void
doPost
(
HttpServletRequest req, HttpServletResponse resp)
throws
IOException, ServletException
{
request.setCharacterEncoding
(
encoding);
response.setContentType
(
"text/html;charset="
+
encoding);
}
}
7. Encodage de la JVM▲
Il est important d'exécuter la JVM dans l'encodage voulu. Le traitement des chaînes de caractères doit être le même que le reste de l'application. C'est au lancement de la JVM, donc au lancement du serveur Java EE, que l'encodage est spécifié à l'aide de l'argument : -Dfile.encoding=UTF-8
Avec Tomcat, cet argument est spécifié dans le fichier de lancement du serveur, catalina.sh.
JAVA_OPTS="$JAVA_OPTS "-Dfile.encoding=utf-8"
Il est parfois également nécessaire de vérifier l'encodage des URL de l'application. Avec Tomcat, cet encodage est déclaré explicitement via l'attribut URIEncoding sur le connecteur Coyote. Voici la ligne du fichier server.xml concerné :
<Connector
port
=
"8080"
maxHttpHeaderSize
=
"8192"
...
URIEncoding
=
"UTF-8"
/>
Le code suivant est très utile car il permet la transformation d'une chaîne de caractères dans un encodage précis.
public
static
String transformStringEncoding
(
String init, String encodingBefore,
String encodingAfter)
{
try
{
return
new
String
(
init.getBytes
(
encodingBefore), encodingAfter);
}
catch
(
UnsupportedEncodingException uee)
{
return
null
;
}
}
8. Gestion de l'encodage▲
Il est tout à fait possible en Java de gérer l'encodage à utiliser. Pour les flots d'entrée par exemple, la connexion est réalisée à l'aide de la classe InputStreamReader. Le jeu de caractères à utiliser peut être alors précisé. Par défaut, le jeu de caractères est fonction du système d'exploitation utilisé et de la localisation (ex : fr_FR UTF-8).
Avec un flot, il est possible de préciser l'encodage utilisé :
InputStreamReader i=
new
InputStreamReader
(
is,"UTF-8"
);
Le nom du jeu de caractères utilisé par défaut est obtenu en programmation avec la méthode System.getProperty() et le paramètre file.encoding.
package
com.betaboutique.classes;
public
class
Programmation {
public
static
void
main
(
String[] args) {
System.out.println
(
"Encodage : "
+
System.getProperty
(
"file.encoding"
));
}
}
Lors des développements Web, il est assez courant que les paramètres reçus par les méthodes HTTP GET et POST ne soient pas dans un format correct. Les problèmes portent alors sur les accents, les caractères spéciaux... Pour cela, la transformation d'un encodage peut être forcé en utilisant les octets. Le code ci-dessous permet de transformer un paramètre reçu en caractères UTF-8.
String parametre=(
String)request.getParameter
(
"parametre"
);
String parametreUTF8=
new
String
(
parametre.getBytes
(
),"UTF-8"
);
De même pour les envois d'informations en programmation Java à travers des flux, l'encodage et les transformations de jeux de caractères sont utilisés.
package
com.betaboutique.classes;
import
java.io.InputStream;
import
java.net.URL;
import
java.net.URLEncoder;
public
class
Programmation {
public
static
void
main
(
String[] args) {
try
{
//paramètre à envoyer en direction du flux
String parametreaenvoyer=
"mon paramètre"
;
String unautreparametreaenvoyer=
"un autre paramètre"
;
String unautreparametreeniso=
"un paramètre en iso"
;
URL url=
new
URL
(
"http://www.essai.com"
+
"?parametre1="
+
URLEncoder.encode (
parametreaenvoyer,"UTF-8"
)
+
"¶metre2="
+
URLEncoder.encode
(
new
String
(
unautreparametreaenvoyer.getBytes
(
), "UTF-8"
),"UTF-8"
)
+
"¶metre3="
+
URLEncoder.encode
(
unautreparametreeniso,"ISO-8859-1"
));
//poster les informations dans le flux
InputStream fluxLecture=
url.openStream
(
);
//fermer le flux
fluxLecture.close
(
);
}
catch
(
Exception e)
{
System.out.println
(
"Erreur de connexion"
);
}
}
}