Vous êtes sur la page 1sur 21

1

Codage de texte et Expressions rgulires

Codage de texte et Expressions rgulires


Sommaire
Codage de texte et Expressions rgulires .......................................................................................... 1 1 2 Introduction ..................................................................................................................................... 2 Les expressions rgulires ............................................................................................................... 3 2.1 2.2 2.3 Les mta-caractres des expressions rgulires ..................................................................... 5 Le Backreferencing .................................................................................................................. 8 Les Regex et le .NET Framework ............................................................................................. 9 Les mthodes de comparaison ...................................................................................... 10 La mthode de remplacement ...................................................................................... 12 Obtention de sous chaines ............................................................................................ 14

2.3.1 2.3.2 2.3.3 3

Codage et dcodage de texte ........................................................................................................ 15 3.1 3.2 3.3 3.4 L'histoire des tables de codages ............................................................................................ 16 Le codage dans le .NET Framework ....................................................................................... 17 Utilisation des classes de codage .......................................................................................... 17 Le Codage et les flux .............................................................................................................. 20

Conclusion ..................................................................................................................................... 21

9 juillet 2008

Codage de texte et Expressions rgulires

1 Introduction
Dans les chapitres prcdents, nous avions vu les bases du Framework ainsi que les diffrentes manires d'accder des donnes.

Dans ce chapitre, nous allons voir comment nous pouvons effectuer des recherches ou des remplacements dans des chanes de caractres en utilisant une mthode de recherche par prototype. Ce procd de recherche est utile lorsqu'on souhaite filtrer des donnes aux provenances non sres (saisie de texte des utilisateurs par exemple) ou juste pour transformer des portions de texte. Nous verrons galement comment sont reprsents les caractres des diffrentes langues en informatique. Ceci permettant l'interoprabilit des textes et de conserver lintgrit des donnes.

9 juillet 2008

Codage de texte et Expressions rgulires

2 Les expressions rgulires


Imaginons que nous crons un nouveau projet dans lequel l'utilisateur peut saisir des informations dont son adresse email par exemple. Nous pourrions vrifier la validit de son adresse via le code suivant:
'VB Sub Main() Console.WriteLine("Entrez votre adresse email :") Dim valeur As String = Console.ReadLine() If (valeur.Contains("@")) Then Console.WriteLine("Adresse email valide") Else Console.WriteLine("Adresse email NON valide") End If Console.Read() End Sub //C# static void Main(string[] args) { Console.WriteLine("Entrez votre adresse email :"); string valeur = Console.ReadLine(); if (valeur.Contains("@")) Console.WriteLine("Adresse email valide"); else Console.WriteLine("Adresse email NON valide"); Console.Read(); }

Ce code fonctionne dans ce cas: Entrez votre adresse email : kikoo@lol.fr Adresse email valide Mais galement dans ces cas l: Entrez votre adresse email : lol@ Adresse email valide Entrez votre adresse email : @ Adresse email valide Le code nous indique qu'il s'agit d'adresse email valide alors qu'en ralit, elles ne le sont pas du tout. En rutilisant le code ci-dessus, nous pourrions ajouter un test afin de vrifier si la chane de caractres contient galement un point. Mais le problme reste entier puisqu'une adresse telle que "43-_@.kl^" ou encore "@." fonctionnerait galement. Si nous devions ainsi tester toutes les formes d'adresses email possibles et imaginables, nous perdrions beaucoup de temps et de performance l'excution. Pour viter ces test successifs, les dveloppeurs Unix et Perl utilisent depuis longtemps ce qu'on appelle les expressions rgulires (Ou "Regex" en raccourci). Les regex permettent, non plus de tester si une chane contient ou non un ou plusieurs caractres, mais de vrifier si une chane de caractres concorde avec un "prototype" de chane de caractres. Par exemple, si on traduit le code prsent ci-dessus, nous pourrions dire "si la chane de caractres contient un @ ".

9 juillet 2008

Codage de texte et Expressions rgulires

Avec les regex, nous pourrions effectuer un test beaucoup plus complet qui se traduirait par : "si la chane de caractres commence par un maximum de 12 caractres alphanumriques, suivis du symbole @, lui-mme suivi par une suite de 5 lettres au maximum, galement suivie d'un point et se terminant par 3 lettres au maximum" et le tout en une seule ligne (ne vous occupez pas de la signification des caractres pour le moment):
'VB Imports System.Text.RegularExpressions Sub Main() Console.WriteLine("Entrez votre adresse email :") Dim valeur As String = Console.ReadLine() If (Regex.IsMatch(valeur, "^(\w{1,12})@([a-z]{1,5})\.([az]{1,3})$", RegexOptions.None)) Then Console.WriteLine("Adresse email valide") Else Console.WriteLine("Adresse email NON valide") End If Console.Read() End Sub //C# static void Main(string[] args) { Console.WriteLine("Entrez votre adresse email :"); string valeur = Console.ReadLine(); if (Regex.IsMatch(valeur, @"^(\w{1,12})@([a-z]{1,5})\.([a-z]{1,3})$", RegexOptions.None)) Console.WriteLine("Adresse email valide"); else Console.WriteLine("Adresse email NON valide"); Console.Read(); }

Cette fois-ci, si nous testons nouveau les adresses prcdentes, nous obtiendrons: Entrez votre adresse email : kikoo@lol.fr Adresse email valide Entrez votre adresse email : lol@ Adresse email NON valide Entrez votre adresse email : abcdefghijklmnop@free.lol Adresse email NON valide Seule la premire adresse rempli tous les critres remplir pour concorder avec la forme de chane de caractres que l'on souhaite tester. Les expressions rgulires permettent de faire beaucoup plus (notamment sur le web o elles permettent de crer du pseudo-code (BBCode) afin de faciliter le traitement de texte sur les forums ou les blogs). Cependant, vous aurez vite remarqu qu'elles ne sont pas trs simples crire et encore moins simples dcrire. Il est important ici de comprendre que, par dfaut, les expressions rgulires sont sensibles la casse, c'est-a-dire quelles font la diffrence entre les lettres majuscules et minuscules. (a et A ont une casse diffrente). 9 juillet 2008

Codage de texte et Expressions rgulires

2.1 Les mta-caractres des expressions rgulires


Vous aurez pu constater grce au code ci-dessus, que les expressions rgulires sont construites grce une chane de caractres (un prototype) dont chaque caractre a une spcification particulire qui est indique dans ces tableaux. Dans la mesure du possible, chaque caractre sera illustr par un exemple rapide : Caractres de positionnement des recherches Caractre Description ^ Indique le dbut de la chane de caractres (Ex: "^a" concordera avec n'importe quelle chane de caractres commenant par la lettre "a"). Sur une chane multi ligne, indique le dbut de n'importe quelle ligne. $ Indique la fin de la chaine de caractres (Ex: "a$" concordera avec n'importe quelle chane de caractres se terminant par un "a"). Sur une chane multi ligne, indique la fin de n'importe quelle ligne. \A Indique que la recherche doit commencer sur le premier caractre de la chane. Les retours la ligne sont ignors (Ex: "\A^a" concordera uniquement si le premier caractre de la premire ligne de la chane de caractres est un "a"). \Z Indique que la recherche doit commencer sur le dernier caractre de la chane ou le dernier caractre situ avant un \n1 terminal. Les retours la ligne sont ignors (Ex: "a$\Z" concordera si les derniers caractres de la dernire ligne de la chane de caractres sont "a" ou "a\n"). \z Indique que la recherche doit commencer sur le dernier caractre de la chane. Les retours la ligne sont ignors (Ex: "a$\z" concordera uniquement si le dernier caractre de la dernire ligne de la chane de caractres est "a"). \G Spcifie que la recherche dbute l o la prcdente recherche s'est arrte. Utilise avec Match.NextMatch(), cela garantie qu'on ne saute aucune occurrence du prototype recherch. \b Spcifie une recherche de mots composs de caractres alpha-numriques (Ex: "\bje\b" concordera uniquement si la chane de caractres contient le mot "je" spar droite et gauche par des caractres non-alphanumriques). \B Spcifie une recherche de morceaux de mots (Ex: "\Bjour\B" concordera uniquement si la chane de caractres contient le mot "jour" entour droite et gauche par des caractres alphanumriques. 1 : Le caractre \n indique un retour la ligne. En VB.NET, il s'agit du caractre vbLf (pour VB Line Feed) 2 : En C#, vous serez oblig de prcder vos prototypes de regex par le symbole @. De cette faon, s'ils contiennent un backslash, ils seront interprts comme des caractres normaux et pas comme un caractre d'chappement.

9 juillet 2008

Codage de texte et Expressions rgulires

Caractres spciaux Caractre Description \a Indique le caractre d'alarme (code Unicode: 0x0007). \b Indique le caractre de retour en arrire (code Unicode: 0x0008) uniquement s'il est utilisant dans un ensemble []. \t Indique le caractre de tabulation (code Unicode: 0x0009). \r Indique le caractre de retour chariot (code Unicode: 0x000D). \v Indique le caractre de tabulation verticale (code Unicode: 0x000B). \f Indique le caractre de dfilement de ligne (code Unicode: 0x000C). \n Indique le caractre de retour la ligne (code Unicode: 0x000A). \e Indique le caractre d'chappement (code Unicode: 0x001B). \040 Reprsente un caractre de la table ASCII en reprsentation octale (les 3 octets sont obligatoires). Ici, \040 reprsente un espace. \x20 Reprsente un caractre de la table ASCII en reprsentation hexadcimale (les 2 valeurs sont obligatoires). Ici, \x20 reprsente aussi un espace. \cC Reprsente un caractre de contrle ASCII. Ici, \cC reprsente la combinaison de touches "CTRL+C". \u0020 Reprsente un caractre de la table Unicode en reprsentation hexadcimale (les 4 valeurs sont obligatoires). \u0020 code aussi pour un espace. \ Lorsqu'on souhaite rechercher un caractre d'expression rgulire, permet d'indiquer la Regex de ne pas traiter le caractre suivant en tant que prototype mais en tant que caractre normal (Ex: "\\" reprsente le caractre "\"). C'est le caractre d'chappement. . Indique n'importe quel caractre except un \n Quantificateurs Caractre Description {x} Spcifie que le caractre prcdent doit apparatre x fois. (Ex: "a{5}" fonctionnera avec "cklaaaaalmp" ou "aaaaa"). {x,} Spcifie que le caractre prcdent doit apparatre au moins x fois (Ex: "a{2,}" fonctionnera avec "cklaa" ou "aa" mais pas avec "a"). {x,y} Spcifie que le caractre prcdent doit apparatre au moins x fois et au plus y fois (Ex: "a{2,3}" fonctionnera avec "aa" ou "aaa" mais pas avec "a" ou "aaaa"). + Le caractre ou l'expression prcdente peut apparatre 1 ou plusieurs fois. Equivalent {1,}. * Le caractre ou l'expression prcdente peut apparatre 0, 1 ou plusieurs fois. Equivalent {0,}. ?1 Le caractre ou l'expression prcdente peut apparatre 0 ou 1 fois. Equivalent {0,1}. Si ce caractre est directement prcd d'un autre quantifieur, il retourne le nombre de rptition le plus petit possible (par exemple, sur la chane "ooooo", si on teste "o+", il retournera tous les o trouvs alors "o+?" ne retournera qu'un seul o. 1 : Lorsque le ? suit un autre quantificateur comme * ou +, il le transforme en mode Ungreedy , cest--dire que le quantificateur va sarrter ds la premire occurrence contenant le moins de caractres possible. Cette technique peut tre utile lorsquon souhaite effectuer du remplacement de chaines de caractres (par exemple, remplacer <tbl.* ?> dans la chaine <tbl>test</tbl><tbl>test2</tbl> ne va affecter que le premier <tbl> disponible ce qui naurait pas t le cas avec <tbl.*> qui aurait remplac toute la chaine).

9 juillet 2008

Codage de texte et Expressions rgulires

Conditions et ensembles de caractres Caractre Description | Permet d'inclure un OU logique entre deux expressions (Ex: "ki|oo" concordera avec n'importe quelle chane contenant soit "ki" soit "oo") [abc] Indique que la chane peut contenir l'une des lettres spcifie dans les crochets (Ex: "[abc]" concordera avec n'importe quelle chane contenant un a, un b ou un c) [a-z] Indique que la chane peut contenir l'un des caractres situs entre a et z (Ex: "[1-9]" concordera avec n'importe quelle chane contenant un chiffre entre 1 et 9) [^abcd] Indique que la chane ne peut contenir aucun des caractres situs dans l'ensemble spcifi. \d Indique un nombre. Equivalent [1-9] \D Indique tout ce qui n'est pas un nombre. Equivalent [^1-9] \s Indique tout ce qui est un espace blanc. Equivalent [\f\n\r\t\v] \S Indique tout ce qui n'est pas un espace blanc. Equivalent [^ \f\n\r\t\v] \w Indique n'importe quel caractre alphanumrique incluant l'underscore. Equivalent [A-Za-z0-9_] \W Indique tout ce qui n'est pas un caractre alphanumrique incluant l'underscore. Equivalent [^A-Za-z0-9_] (abc) Permet de spcifier un groupe indissociable de caractres (Ex: "t(ia|ol)t" concordera avec tiat ou tolt) Les groupes nomms Il est possible de crer des variables temporaires (appeles "groupes nomms") qui stockeront un rsultat trouv. Pour ce faire, vous devez utiliser la syntaxe "(?<nom>prototype)". Par exemple, si nous cherchons "\[(?<valeur>\d)\]", cela concordera avec les chanes contenant la forme de texte "[x]" o x est un chiffre dcimal. Vous pourrez ensuite accder ce chiffre en utilisant la variable valeur.

9 juillet 2008

Codage de texte et Expressions rgulires

2.2 Le Backreferencing
Le Backreferencing, c'est le fait d'utiliser les groupes nomms (explicitement ou non) avant de s'en servir nouveau directement dans le prototype. Pour cela, on utilise les caractres de regroupements (les parenthses) pour dfinir la backreference. On utilise ensuite le caractre \, pour faire appel un groupe nomm implicitement, ou le caractre \k, pour appeler un groupe nomm explicitement. Ainsi: "(\d)\1" cr une backreference nomme implicitement, indiquant n'importe quel chiffre dcimal et rutilise la backreference de suite aprs. Ce code concorde donc avec toute chane contenant deux chiffres identiques qui se suivent. "(?<char>\w)\k<char>" cr une backreference nomme. Dans cet exemple, la backreference s'appelle char et est rutilise de suite aprs. Ce code concorde donc avec toute chane contenant deux caractres identiques qui se suivent. Comme les expressions rgulires s'excutent de manire procdurale, si deux backreferences nommes portant le mme nom, sont dfinies dans la mme Regex, seule la dernire backreference sera utilise. Nous avons galement remarqu que les backreference sans nom sont implicitement nommes 1, 2, 3 etc . Il est tout fait possible de nommer ces backreference en utilisant l'un de ces nombres et d'y accder comme si c'tait une backreference non nomme (Ex: "(?<1>\w)\1" est quivalent "(\w)\1").

9 juillet 2008

Codage de texte et Expressions rgulires

2.3 Les Regex et le .NET Framework


Tous les outils ncessaires l'utilisation des Regex se trouvent dans l'espace de nom System.Text.RegularExpressions. On y trouve notamment la classe Regex qui propose quelques mthodes statiques pour utiliser les regex: Mthode Description IsMatch Retourne un boolen indiquant si le prototype de chane de caractres a t trouve dans la chane de caractres spcifie. Match Retourne un objet de type Match contenant l'occurrence de la recherche du prototype dans la chane de caractres spcifie. Matches Retourne un objet MatchCollection contenant les rsultats de toutes les occurrences du prototype qui ont t trouves dans la chane de caractres. Replace Dans une chane de caractres, remplace toutes les occurrences du prototype par une chane de caractres indique. Split Coupe une chane de caractres aux positions dfinies par un prototype. Dans chacune de ces mthodes, nous pouvons indiquer l'une des valeurs de l'numration RegexOptions (ou plusieurs valeurs en effectuant un OU logique entre chacune). A chaque valeur de l'numration correspond galement une lettre pour que l'on puisse spcifier des options supplmentaires l'intrieur du prototype de recherche (toutes les options ne sont pas utilisables dans un prototype). Pour cela, nous utilisons les caractres de regroupement par exemple "(?ix-ms)" indique d'ignorer la casse et les espaces blancs du prototype et annule le multi-ligne ainsi que l'option Singleline (le caractre - indiquant la ngation de l'option). Voici les options disponibles : Valeur Valeur Inline Description None Aucune option IgnoreCase i Spcifie la sensibilit la casse. Multiline m Spcifie le mode multi-ligne. Change le comportement des caractres ^et $. ExplicitCapture n Spcifie que seule les captures nommes sont autorises (avec la forme "(?<nom>)" ) Compiled Spcifie que le prototype est contenu dans un assembly compil en code MSIL. Permet une excution plus rapide. Singleline s Spcifie le mode "une seule ligne". Change le comportement de "." qui indique alors n'importe quel caractre except \n. IgnorePatternWhitespace x Spcifie que n'importe quel espace blanc non chapp sera ignor. Active les commentaires grce au caractre #. RightToLeft Spcifie que la recherche sera effectue en partant de la droite et non en partant de la gauche. ECMAScript Spcifie un comportement conforme l'ECMAScript. Cette option ne peut tre utilise qu'avec Multiline et IgnoreCase. CultureInvariant Spcifie que les diffrences culturelles dans la langue ne sont pas prises en compte.

9 juillet 2008

10

Codage de texte et Expressions rgulires

2.3.1

Les mthodes de comparaison La mthode IsMatch est la plus simple de toutes. Elle prend en paramtre la chane que l'on souhaite tester, le prototype tester et ventuellement des options.
'VB Sub Main() Console.WriteLine("Entrez votre numero de telephone:") Dim numero As String = Console.ReadLine() Console.WriteLine("Validite du numero: {0}", Regex.IsMatch(numero, "^(\d{2}\u0020){4}\d{2}\u0020?$")) End Sub //C# static void Main(string[] args) { Console.WriteLine("Entrez votre numero de telephone:"); string numero = Console.ReadLine(); Console.WriteLine("Validite du numero: {0}", Regex.IsMatch(numero, @"^(\d{2}\u0020){4}\d{2}\u0020?$")); } Ce code se contente de vrifier qu'un numro de tlphone est bien sous la forme "12 34 56 78 90". Toute autre forme indiquera que le numro n'est pas correct.

La Regex utilise est simple. Elle vrifie si la chane commence par 4 nombres de deux chiffres chacun, suivis d'un espace et se termine par un nombre de deux chiffres. Optionnellement, il est possible que le numro soit termin par un espace blanc. Entrez votre numero de telephone: 05 61 45 67 89 Validite du numero: True La mthode Match peut tre utile si on souhaite rcuprer des informations qui auraient pu tre captures au cours de la recherche. En effet, cette mthode retourne un objet de type Match qui contient tous les paramtres de la premire occurrence trouve dans la chane de caractres. Dans la mme optique, la mthode Matches retourne un objet MatchCollection (une liste d'objet Match) qui contient l'ensemble des occurrences du prototype dans la chane de caractres.

9 juillet 2008

11

Codage de texte et Expressions rgulires

L'exemple ci-dessous demande d'entrer une phrase. Dans cette phrase, on peut saisir des tags sous la forme "tag:valeur". Ainsi, chaque tag pourra tre rcupr par la suite et on pourra galement rcuprer la valeur entre par l'utilisateur:
'VB Sub Main() Console.WriteLine("Entrez une phrase (peut contenir des tag 'tag:valeur'):") Dim chaine As String = Console.ReadLine() Dim collection As MatchCollection = Regex.Matches(chaine, "\u0020?(?<tag>\w+):(?<valeur>\w+)\u0020?") For Each m As Match In collection Console.WriteLine("Le tag {0} contient la valeur {1}", m.Groups("tag"), m.Groups("valeur")) Next End Sub //C# static void Main(string[] args) { Console.WriteLine("Entrez une phrase (peut contenir des tag 'tag:valeur'):"); string chaine = Console.ReadLine(); MatchCollection collection = Regex.Matches(chaine, @"\u0020?(?<tag>\w+):(?<valeur>\w+)\u0020?"); foreach(Match m in collection) { Console.WriteLine("Le tag {0} contient la valeur {1}", m.Groups["tag"], m.Groups["valeur"]); } }

Ce qui donne: Entrez une phrase (peut contenir des tag 'tag:valeur'): Bonjour, je suis name:Kikoo firstname:LoL . Je suis un type:programme intelligen t Le tag name contient la valeur Kikoo Le tag firstname contient la valeur LoL Le tag type contient la valeur programme

9 juillet 2008

12

Codage de texte et Expressions rgulires

2.3.2

La mthode de remplacement Lors de vos recherches, vous pouvez remplacer uniquement des portions de textes tout en conservant des valeurs du prototype qui ont t captures. Pour cela, vous devez crer une variable temporaire du mot que vous souhaitez conserver et dans le paramtre de remplacement de la mthode Replace, vous utiliserez "${nom_de_variable}" pour rcuprer ce qui a t sauvegard. Par exemple, nous pourrions vouloir remplacer tous les verbes l'infinitif par leur impratif. Cet exemple ne va convertir que les verbes du premier groupe:
'VB Sub Main() Dim verbe() As String = {"acheter", "achever", "priver", "manger", "poutrer"} For Each v As String In verbe Console.WriteLine(Regex.Replace(v, "(?<base>.+)(er)$", "${base}e", RegexOptions.Singleline)) Next End Sub //C# static void Main(string[] args) { Console.WriteLine("---Retourne l'impratif--"); String[] verbe = {"acheter", "achever", "priver", "manger", "poutrer"}; foreach(string v in verbe) { Console.WriteLine(Regex.Replace(v, "(?<base>.+)(er)$", "${base}e", RegexOptions.Singleline)); } }

Plusieurs variables de substitution sont cres lorsque vous utilisez Replace: Caractres Description $nombre Remplace par une capture nomme implicitement (en utilisant la forme "(expression)") ${nom} Remplace par une capture nomme explicitement (en utilisant la forme "(?<nom>expression)" $$ Remplace par un seul $ $& Remplace par une copie de tout le prototype. $` Remplace tout le texte test avant l'application du prototype $' Remplace tout le texte test aprs l'application du prototype $_ Remplace par le dernier groupe captur $+ Remplace par toute la chane teste

9 juillet 2008

13

Codage de texte et Expressions rgulires

Cet autre exemple, bien connu des concepteurs de forums, va ouvrir un fichier et convertir quelques balises BBcode simples de la faon suivante: [code]donnee[/code] en <code>donnee</code> [code=valeur]donnee[/code] en <span style='code:valeur;'>donnee</span>
'VB Sub Main() Dim texte As String = File.ReadAllText("c:\Test\test1.txt") Console.WriteLine("---Avant transformation---" + vbNewLine + texte) texte = Regex.Replace(texte, "\[(?<code>[az]{1,3})\](?<donnee>.+)\[/\k<code>\]", "<${code}>${donnee}</${code}>", RegexOptions.Multiline) texte = Regex.Replace(texte, "\[(?<code>[a-z]{1,6})=(?<valeur>#([AF]|[0-9]){6})\](?<donnee>.+)\[/\k<code>\]", "<span style='${code}=${valeur}'>${donnee}</${code}>", RegexOptions.Multiline) Console.WriteLine(vbNewLine + vbNewLine + "---Aprs transformation--" + vbNewLine + texte) Console.Read() End Sub //C# static void Main(string[] args) { string texte = File.ReadAllText(@"c:\Test\test1.txt"); Console.WriteLine("---Avant transformation---" + "\n" + texte); texte = Regex.Replace(texte, @"\[(?<code>[az]{1,3})\](?<donnee>.+)\[/\k<code>\]", "<${code}>${donnee}</${code}>", RegexOptions.Multiline); texte = Regex.Replace(texte, @"\[(?<code>[a-z]{1,6})=(?<valeur>#([AF]|[0-9]){6})\](?<donnee>.+)\[/\k<code>\]", "<span style='${code}=${valeur}'>${donnee}</${code}>", RegexOptions.Multiline); Console.WriteLine("\n" + "\n" + "---Aprs transformation---" + "\n" + texte); }

---Avant transformation--Bonjour, Je [b]suis[/b] du texte [b]traduit[/b] [i]en HTML[/i]. En plus, je peux etre [color=#FF0000]rouge[/color]

---Aprs transformation--Bonjour, Je <b>suis</b> du texte <b>traduit</b> <i>en HTML</i>. En plus, je peux etre <span style='color=#FF0000'>rouge</color>

9 juillet 2008

14

Codage de texte et Expressions rgulires

2.3.3

Obtention de sous chaines Comme nous l'avons vu, il est galement possible de scinder la chane d'entre chaque occurrence d'un prototype grce la mthode Split. Voici un exemple qui coupe la phrase chaque fois qu'elle trouve un chiffre dcimal
'VB Sub Main() Console.WriteLine("Entrez une phrase avec des chiffres:") Dim chaine As String = Console.ReadLine() Dim words() As String = Regex.Split(chaine, "\d", RegexOptions.Singleline) Console.WriteLine(vbNewLine + vbNewLine + "----La chaine contient les parties suivantes----") For Each s As String In words Console.WriteLine(s) NextEnd Sub End Sub //C# static void Main(string[] args) { Console.WriteLine("Entrez une phrase avec des chiffres:"); chaine = Console.ReadLine(); String[] words = Regex.Split(chaine, @"\d", RegexOptions.Singleline); Console.WriteLine("\n" + "\n" + "----La chaine contient les parties suivantes----"); foreach (string s in words) { Console.WriteLine(s); } }

Ce qui donne: Entrez une phrase avec des chiffres: Bonjour je suis4une regex1trs trs5utile

----La chaine contient les parties suivantes---Bonjour je suis une regex trs trs utile

9 juillet 2008

15

Codage de texte et Expressions rgulires

3 Codage et dcodage de texte


Le codage et le dcodage de textes nest pas une notion facile comprendre. Cela lest dautant moins avec le Framework .NET car il gre implicitement les codages et dcodages par dfaut. Pourtant, le codage et le dcodage de textes va nous tre trs utile dans plusieurs cas : Rendre nos documents interoprables avec dautres systmes dexploitation Lire et crire des documents dans plusieurs langues Vous aurez par exemple besoin dindiquer que vous utilisez une langue latine pour envoyer un e-mail un japonais, ou bien dutiliser un codage Unicode pour envoyer un document texte une machine UNIX. La table ci-contre nous montre le contenu de la table ASCII. Pour obtenir une valeur numrique correspondant une lettre, on localise la lettre coder, on regarde d'abord le numro de colonne attribu puis le numro de ligne ('A' est cod 41 en hexadcimal)

9 juillet 2008

16

Codage de texte et Expressions rgulires

3.1 L'histoire des tables de codages


Le codage nous lavons vu dans lintroduction tend normaliser la manire de transformer du code machine en texte. Lorsque lon code un texte, quelque soit le type de codage utilis, celui-ci va tre transform en une squence doctets. Le dcodage est le processus inverse, celui de transformer ces octets en texte. Le premier type de codage normalis est lAmerican Standard Code For Information Interchange (ASCII). Il a t cr par lAmerican National Standard Institute (ANSI) et est le pilier des codages normaliss puisque la plupart sen servent de base aujourdhui. LASCII est une table de caractres code sur 7 bits (elle supporte donc 128 caractres). Chaque nombre compris entre 0 et 127 est assign un point de code. Cela peut tre un caractre alphanumrique, un caractre spcial, ou une commande de contrle. Par exemple, la lettre P correspondant en hexadcimal 0x50, @ 0x40, et la commande SPACE (espace) correspond 0x20. Note : Vous trouverez une reprsentation trs dtaill de la table ASCII en suivant ce lien.

Lorganisme de normalisation international ISO a ensuite repris les bases de lANSI pour crer de nouveaux types de codage, notamment les ISO-8859-xx. LISO a redfini la norme de codage en codant non plus sur 7 bits mais sur 8. Ainsi, de 0 127 correspond la table ASCII, puis de 128 255 correspondent tous les caractres spciaux (lettres accentues par exemple). Certaines langues contenant de nombreux caractres sont codes sur 16 bits (japonais, chinois). Le problme de ces codages en ASCII tendu 8 bits est quils font correspondre des caractres diffrents pour une mme valeur sur la plage 127 255, il est alors impossible de mlanger dans un mme document deux alphabets diffrents (Franais et Hbreux par exemple). Aussi, un nouveau standard appel Unicode a t cre en 1991. Celui-ci couvre les caractres de plusieurs langages diffrents dont les caractres chinois, japonais, Cyrillique, Hbreux Au total aprs la mise jour de juillet 2006 (version 5.0), lUnicode regroupait 245 000 points de codes. Vous pouvez bien entendu utiliser les caractres de plusieurs langues diffrentes dans un seul et mme document ! Ainsi si vous envoyez deux versions d'un e-mail (l'un en codage ISO et l'autre en Unicode) un Japonais, si celui-ci ne possde pas les informations ncessaires pour lire le codage ISO de votre langue, seul le-mail cod en Unicode aura gard son intgrit. Quand vous dveloppez des programmes, veillez donc toujours faire attention aux problmes de codage. Une bonne pratique consiste utiliser lUnicode, en effet, il est gr sur toutes les machines par dfaut.

9 juillet 2008

17

Codage de texte et Expressions rgulires

3.2 Le codage dans le .NET Framework


Le Framework .NET gre plusieurs types de codages grce des classes contenues dans System.Text.
Codage
ASCII/ISO/Unicode

ASCII Unicode UTF-8

Unicode UTF-16

Unicode UTF-32

Description Regroupe un large panel des codages ASCII, ISO et Unicode existants qui sont grs par la classe System.Text.Encoding Vous pouvez retrouver la liste en suivant ce lien. Permet dencoder en US ASCII sur 7 bits grce la classe ASCIIEncoding Permet dencoder en Unicode UTF-8 grce la classe UTF8Encoding. LUTF-8 est cod sur un quatre octets et permet une transition facile en Unicode depuis un codage ANSI/ISO. Le Framework .NET utilise lUTF-8 dans certains processus internes. Vous pouvez retrouver une large description de lUTF-8 en suivant ce lien. Permet dencoder en Unicode UTF-16 grce la classe UnicodeEncoding. LUTF-16 est cod sur un ou deux mots de 16 bits. Cest le codage utilis par le Framework .NET pour afficher un caractre. Vous pouvez retrouver une large description de lUTF-16 en suivant ce lien. Permet dencoder en Unicode UTF-32 grce la classe UTF32Encoding. LUTF-32 est cod sur un mot double de 32 bits. Vous pouvez retrouver une large description de lUTF-32 en suivant ce lien.

3.3 Utilisation des classes de codage


Afin de comprendre comment fonctionne le codage dun texte de faon explicite, voici une suite dexemple :
'VB Sub Main() Dim e As Encoding = Encoding.GetEncoding("iso-8859-1") Dim encode() As Byte encoded = e.GetBytes("Bonjour!") For i As Integer = 0 To encode.Length Console.WriteLine("Octet {0}: {1}", i, encode(i)) Next Console.Read() End Sub //C# static void Main(string[] args) { Encoding e = Encoding.GetEncoding("iso-8859-1"); byte[] encode; encode = e.GetBytes("Bonjour!"); for (int i = 0; i < encode.Length; i++) Console.WriteLine("Octet {0}: {1}", i, encode[i]); Console.Read(); }

9 juillet 2008

18

Codage de texte et Expressions rgulires

Nous rcuprons donc un objet de type Encoding grce la mthode GetEncoding de la classe Encoding. Puis nous codons grce cet objet le texte Bonjour! . Enfin nous affichons la reprsentation code de notre texte. Voici ce que la console affiche : Octet 0: 66 Octet 1: 111 Octet 2: 110 Octet 3: 106 Octet 4: 111 Octet 5: 117 Octet 6: 114 Octet 7: 33 Vous pouvez constater que les lettres ont toutes t transformes en valeurs binaires, qui sont affiches en dcimal par la mthode WriteLine de la classe Console. Comme nous avons utilis les lettres contenues dans la table ASCII, vous pouvez voir que les valeurs sont comprises entre 0 et 127, le dcodage sera possible dans nimporte quel codage utilisant au minimum un octet. Si nous utilisons maintenant un texte cod en franais et que nous le transformons en hbreu, voici ce qui l va se passer :
'VB Sub Main() Dim e As Encoding = Encoding.GetEncoding("iso-8859-1") Dim f As Encoding = Encoding.GetEncoding("iso-8859-8") Dim encode() As Byte encode = e.GetBytes("Bonjour! ") Console.WriteLine(f.GetString(encode)) Console.Read() End Sub //C# static void Main(string[] args) { Encoding e = Encoding.GetEncoding("iso-8859-1"); Encoding f = Encoding.GetEncoding("iso-8859-8"); byte[] encode; encode = e.GetBytes("Bonjour! "); Console.WriteLine(f.GetString(encode)); Console.Read(); }

Bonjour! ??????? La mthode GetString va transformer la suite doctets en une chane de caractres. Comme vous pouvez le voir, tous les caractres accentus spcifiques la langue franaise et qui nexistent pas en hbreu sont transforms en point dinterrogations, ce qui indique quils nont pas pu tre dcods.

9 juillet 2008

19

Codage de texte et Expressions rgulires

Si vous souhaitez toutefois convertir dans un autre langage tout en gardant une certaine intgrit du texte, vous pouvez utiliser la mthode Convert de la classe Encoding.
'VB Sub Main() Dim e As Encoding = Encoding.GetEncoding("iso-8859-1") Dim f As Encoding = Encoding.GetEncoding("iso-8859-8") Dim encode() As Byte encode = e.GetBytes("Bonjour! ") Dim decode() As Byte = Encoding.Convert(e, f, encode) Console.WriteLine(f.GetString(decode)) Console.Read() End Sub //C# static void Main(string[] args) { Encoding e = Encoding.GetEncoding("iso-8859-1"); Encoding f = Encoding.GetEncoding("iso-8859-8"); byte[] encode; byte[] decode; encode = e.GetBytes("Bonjour! "); decode = Encoding.Convert(e, f, encode); Console.WriteLine(f.GetString(decode)); Console.Read(); }

Bonjour! eeaoiue

9 juillet 2008

20

Codage de texte et Expressions rgulires

3.4 Le Codage et les flux


Nous lavons vu dans le chapitre prcdent, il est possible de prciser lencodage dun fichier lorsque lon ouvre un flux de type StreamReader ou StreamWriter. Nous allons effectuer un petit rappel en utilisant un type de codage plus exotique : lUTF7.
'VB Sub Main() Dim fluxEcriture As StreamWriter = New StreamWriter("c:\Test\test.txt", False, Encoding.UTF7) fluxEcriture.WriteLine("Bonjour! ") fluxEcriture.Flush() fluxEcriture.Close() Dim fluxLecture As StreamReader = New StreamReader("c:\Test\test.txt", Encoding.UTF7) Console.WriteLine(fluxLecture.ReadToEnd()) fluxLecture.Close() Console.Read() End Sub //C# static void Main(string[] args) { StreamWriter fluxEcriture = new StreamWriter(@"c:\Test\test.txt", false, Encoding.UTF7); fluxEcriture.WriteLine("Bonjour! "); fluxEcriture.Flush(); fluxEcriture.Close(); StreamReader fluxLecture = new StreamReader(@"c:\Test\test.txt", Encoding.UTF7); Console.WriteLine(fluxLecture.ReadToEnd()); fluxLecture.Close(); Console.Read(); }

Nous crivons ici un texte compos de caractres spciaux (point dexclamation et lettres accentues) dans un fichier puis nous le lisons en utilisant le codage UTF7. La console indique le bon texte : Bonjour! Mais si on tente de lire le fichier avec Notepad, voil le rsultat. Bonjour+ACE- +AOkA6ADgAPQA7gD7AOo-

9 juillet 2008

21

Codage de texte et Expressions rgulires

4 Conclusion
Nous avons vus qu'en informatique, les caractres tels qu'ils apparaissent l'cran, sont cods grce des tables de caractres qui effectuent une correspondance entre un chiffre et une lettre, dans une ou plusieurs langues. Nous avons galement vu que le .NET Framework fourni un support assez complet permettant l'utilisation des expressions rgulires. Ces expressions nous permettent d'effectuer des modifications sur du texte en utilisant non plus des squences de caractres mais des prototypes de texte. Concernant les expressions rgulires, il ne vous est pas demand de retenir absolument tous les caractres utilisables. Seuls les plus utiles doivent tre connues. Ainsi, la fin de ce chapitre, vous devez tre capable de: Comprendre l'utilit des expressions rgulires Formuler des regex fonctionnelles (Savoir reproduire les exemples de ce chapitre devrait tre une base). Comprendre l'intrt des tables de codages. Savoir passer un texte d'un type de codage un autre. Dans tous les cas, vous pouvez aller visiter le MSDN qui possde non seulement la documentation technique sur les outils d'encodage et d'expressions rgulires mais galement des tutoriaux et des documents sur les concepts d'utilisation de ces outils.

9 juillet 2008