[R] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Règles du forum
- Merci de consulter la section "Règles du forum" et plus particulièrement "Règles et Mentions Légales du site autoitscript.fr" avant d'écrire un message.
- jchd
- AutoIt MVPs (MVP)

- Messages : 2283
- Enregistré le : lun. 30 mars 2009 22:57
- Localisation : Sud-Ouest de la France (43.622788,-1.260864)
- Status : Hors ligne
[R] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Bien le bonsoir,
Ma question peut étonner, mais j'ai un gros doute sur la gestion des chaînes UTF-8 et surtout UTF-16 (-le en l'occurence) sous AutoIt.
Ainsi StringLen renvoie la longueur en _octets_ d'une chaîne UTF-8 au lieu de sa longueur en _caractères_.
Mais ce qui me surprend le plus, c'est le résultat de la conversion en UTF-16 d'une chaîne ANSI ou UTF-8. Le contenu de la structure (et pourquoi n'emploie-t-on pas un type wstr ?) renvoyée par _WinAPI_MultiByteToWideChar est une chaîne ASCII contenant la représentation hexa de la chaîne UTF-16 souhaitée (e.g. "0xE900C7000000"). De même, StringLen renvoie la longueur en octets de la "chose" ci-dessus...
Je peux poster un bout de code pour démontrer ceci.
Quelle est donc la sémantique UTF-* d'AutoIt ?
Ma question peut étonner, mais j'ai un gros doute sur la gestion des chaînes UTF-8 et surtout UTF-16 (-le en l'occurence) sous AutoIt.
Ainsi StringLen renvoie la longueur en _octets_ d'une chaîne UTF-8 au lieu de sa longueur en _caractères_.
Mais ce qui me surprend le plus, c'est le résultat de la conversion en UTF-16 d'une chaîne ANSI ou UTF-8. Le contenu de la structure (et pourquoi n'emploie-t-on pas un type wstr ?) renvoyée par _WinAPI_MultiByteToWideChar est une chaîne ASCII contenant la représentation hexa de la chaîne UTF-16 souhaitée (e.g. "0xE900C7000000"). De même, StringLen renvoie la longueur en octets de la "chose" ci-dessus...
Je peux poster un bout de code pour démontrer ceci.
Quelle est donc la sémantique UTF-* d'AutoIt ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
- orax
- Modérateur

- Messages : 1479
- Enregistré le : lun. 23 mars 2009 04:50
- Localisation : ::1
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
En utilisant String() ça semble marcher, ça me retourne bien le nombre de caractères UTF-8 et non le nombre d'octets, mais je ne sais pas si c'est une bonne solution de procéder ainsi...jchd a écrit :Ainsi StringLen renvoie la longueur en _octets_ d'une chaîne UTF-8 au lieu de sa longueur en _caractères_.
Code : Tout sélectionner
StringLen(String($CARACTERES_UTF8))Et éventuellement placez un bout de code pour démontrer le reste du message.
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
- jchd
- AutoIt MVPs (MVP)

- Messages : 2283
- Enregistré le : lun. 30 mars 2009 22:57
- Localisation : Sud-Ouest de la France (43.622788,-1.260864)
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
De pénibles essais démontrent le contraire, pourtant. Que mets-tu dans $CARACTERES_UTF8 ?orax a écrit :En utilisant String() ça semble marcher, ça me retourne bien le nombre de caractères UTF-8 et non le nombre d'octets, mais je ne sais pas si c'est une bonne solution de procéder ainsi...A propos, concernant sa limitation au niveau de l'Unicode, il y a une page dans l'aide à : Autoit \ Using Autoit \ Unicode Support.Code : Tout sélectionner
StringLen(String($CARACTERES_UTF8))
Et éventuellement placez un bout de code pour démontrer le reste du message.
Tiens, voici un bout de code simple, à utiliser avec un éditeur UTF-8/16 aware, comme Scite, PsPad ou autre :
Code : Tout sélectionner
Global $c = "€"
Run("Notepad.exe", "", @SW_MAXIMIZE)
WinWaitActive("Sans titre")
ClipPut($c & @TAB & StringToBinary($c) & @TAB & StringLen($c) & @CRLF) ; et hop, dans le clipboard
Send("^V" & "{ENTER 2}") ; qu'on colle dans NotePad : problème !
Si on le lance à partir du même source stocké cette fois en UTF-16, le caractère Euro s'affiche correctement, le code est 0x80 au lieu de 0x20AC, et la longueur est bien 1 !
Attention à ne pas avoir transformé le source en ANSI dans les manips !
Maintenant le script suivant utilise des caractères franchement exotiques, ce qui montre si on n'a pas fait de conversion en ANSI sans s'en rendre compte. L'ensemble ne fonctionne convenablement qu'à partir d'un source UTF-16 et non pas UTF-8.
Code : Tout sélectionner
#include <Array.au3>
Global $saUtf[14] = [ _
"Unicode strings", _
"Arial Unicode MS", _
"", _
"Chaîne 1 逬逮週邅邇邈邉", _
"Chaîne 2 阳阴阵阶阷阸阹", _
"Chaîne 3 갷갸갹갺갻갼갽", _
"Chaîne 4 쨻쩤챃챘챭첂챱", _
"Chaîne 5 蠟老虜寧復磻北", _
"Chaîne 6 ﯕﮡﮏﭼﰉﲥﳆﱧﳹ", _
"Chaîne 7 ﺤﺕﺅ3ﻨﻑﻎﺻﻔᆭᆵᆳᄍ₩ツ", _
"Chaîne 8 ໓ືໃ༓༌ཝཿཥᄆᄲᄶᅤ", _
"Chaîne 9 DŽǍdzǯɧƢƧƔƝƠǼ", _
"Chaîne 10 ďĠĞŒŎƊŻŧũΖΫίΩΧΦѮҖѩҟҢ", _
"Chaîne 11 ∀ x∈ℕ, ∃! y∈ℕ / y = x!"]
Run("Notepad.exe", "", @SW_MAXIMIZE)
WinWaitActive("Sans titre")
Send("!OP") ; on appelle la police ;-)
Send($saUtf[1]) ; Arial Unicode MS, dispo sur tout XP
Send("{TAB 2}16") ; en corps 16, siouplé
Send("{ENTER}")
ClipPut(_ArrayToString($saUtf, @CRLF)) ; et hop, dans le clipboard
Send("^V" & "{ENTER 2}") ; qu'on colle dans NotePad : nickel
Je n'ai toujours pas trouvé comment convertir entre UTF-8 et UTF-16. C'est quand même étonnant que toutes les recherches ne remontent rien de valable. Il doit quand même exister un nombre certain d'usagers qui ont besoin de ça, non ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
- orax
- Modérateur

- Messages : 1479
- Enregistré le : lun. 23 mars 2009 04:50
- Localisation : ::1
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Je suis allé sur google.cn, j'ai copié quelques caractères chinois 高级搜索 que j'ai mis dans notepad, puis enregistré en UTF-8. Concernant le code complet que j'ai utilisé c'est :De pénibles essais démontrent le contraire, pourtant. Que mets-tu dans $CARACTERES_UTF8 ?
Code : Tout sélectionner
#include <debug.au3>
$c = FileRead("fichier_UTF8.txt")
$longueur=StringLen(String($c))
MsgBox(0, $longueur,$c)
; ou pour l'afficher dans notepad :
_DebugSetup()
_DebugOut($longueur & " - " & $c)De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
- jchd
- AutoIt MVPs (MVP)

- Messages : 2283
- Enregistré le : lun. 30 mars 2009 22:57
- Localisation : Sud-Ouest de la France (43.622788,-1.260864)
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
De plus en plus étrange !
En effet, si tu copies/colles tes 4 idéogrammes dans une chaîne littérale à la place de ta lecture fichier, tu n'obtient pas le même résultat.
Tout ça me semble complètement inexploitable. Car j'ai une base en ANSI et deux bases UTF SQLite une en 8 et l'autre en 16. Et j'ai déjà développé _beaucoup_ de morceaux de code pour ficeler mon appli. Je peux difficilement switcher sur un autre développement maintenant.
Pourtant, AutoIt est puissant et séduisant, mais là... il y a trop de comportement caché. Si au moins on pouvait jeter un oeil sur les sources, ça permettrait éventuellement de piger le pourquoi de ce fatras.
Je suis dans une m.... noire du coup.
En effet, si tu copies/colles tes 4 idéogrammes dans une chaîne littérale à la place de ta lecture fichier, tu n'obtient pas le même résultat.
Tout ça me semble complètement inexploitable. Car j'ai une base en ANSI et deux bases UTF SQLite une en 8 et l'autre en 16. Et j'ai déjà développé _beaucoup_ de morceaux de code pour ficeler mon appli. Je peux difficilement switcher sur un autre développement maintenant.
Pourtant, AutoIt est puissant et séduisant, mais là... il y a trop de comportement caché. Si au moins on pouvait jeter un oeil sur les sources, ça permettrait éventuellement de piger le pourquoi de ce fatras.
Je suis dans une m.... noire du coup.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
- orax
- Modérateur

- Messages : 1479
- Enregistré le : lun. 23 mars 2009 04:50
- Localisation : ::1
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Je viens de tester avec le fichier source encodé. J'ai remarqué que les caractères ne s'affichent pas bien quand le fichier est encodé en "UTF-8 (sans BOM)" et UNIQUEMENT en "UTF-8 (sans BOM)". J'ai bien ceci qui s'affiche sur le notepad (sans rien changer à votre code, bien sûr) :
► Afficher le texte
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
- orax
- Modérateur

- Messages : 1479
- Enregistré le : lun. 23 mars 2009 04:50
- Localisation : ::1
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Je rajoute un code qui chez moi, marche sans problème sauf en UTF8 (sans BOM) :
► Afficher le texte
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
- jchd
- AutoIt MVPs (MVP)

- Messages : 2283
- Enregistré le : lun. 30 mars 2009 22:57
- Localisation : Sud-Ouest de la France (43.622788,-1.260864)
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Oui, le ClipPut fonctionne, mais rien n'est orthogonal !
Pourquoi et quand doit-on "caster" une variable chaîne en chaîne pour qu'elle soit reconnue à sa juste longueur ?
Pourquoi constate-t-on une différence de principe de fonctionnement entre UTF-8 et 16 ?
Pourquoi les différences entre variables lues et littéraux ?
Le résultat de ce code me laisse perplexe. Source stocké en UTF-8 + BOM et les 4 idéogrammes dans le fichier utf8.txt sont identiques au littéral.
Ce qui produit :
La variable castée est égale au littéral non casté, mais la première s'affiche et pas l'autre !
Les binaires sont tous faux !
Mouais, il se passe de drôles de choses en UTF-8.
Demain, j'essaie l'UTF-16.
Pourquoi et quand doit-on "caster" une variable chaîne en chaîne pour qu'elle soit reconnue à sa juste longueur ?
Pourquoi constate-t-on une différence de principe de fonctionnement entre UTF-8 et 16 ?
Pourquoi les différences entre variables lues et littéraux ?
Le résultat de ce code me laisse perplexe. Source stocké en UTF-8 + BOM et les 4 idéogrammes dans le fichier utf8.txt sont identiques au littéral.
Code : Tout sélectionner
#include <debug.au3>
_DebugSetup("strings")
Send("!OP") ; on appelle la police ;-)
Send("Arial Unicode MS") ; Arial Unicode MS, dispo sur tout XP
Send("{TAB 2}16") ; en corps 16, siouplé
Send("{ENTER}")
$fileVar = FileRead("utf8.txt") ; 4 idéogrammes en UTF-8 with BOM (3 de BOM et 12 octets)
$fileVar_Cast = String($fileVar) ; version "cast" de la chaîne lue
$litteral = "高级搜索" ; 4 caractères UTF-8 identiques au contenu du fichier
$litteral_Cast = String($litteral) ; version "cast" du littéral
_DebugOut( @TAB & @TAB & @TAB & "$fileVar" & @TAB & @TAB & "$litteral")
_DebugOut("----------------------------------------------------------------------------------------------")
_DebugOut("Chaîne ?" & @TAB & @TAB & @TAB & (IsString($fileVar)==1) & @TAB & @TAB & (IsString($litteral)==1))
_DebugOut("Chaîne Cast ?" & @TAB & @TAB & (IsString($fileVar_Cast)==1) & @TAB&@TAB & (IsString($litteral_Cast)==1))
_DebugOut("Chaîne==Cast ?" & @TAB & @TAB & ($fileVar == $fileVar_Cast) & @TAB&@TAB & ($litteral == $litteral_Cast))
_DebugOut("Variable == littéral ?" & @TAB & @TAB & @TAB & ($fileVar == $litteral))
_DebugOut("Variable Cast == littéral Cast ?" &@TAB&@TAB & ($fileVar_Cast == $litteral_Cast))
_DebugOut("Variable Cast == littéral ?" &@TAB&@TAB & ($fileVar_Cast == $litteral))
_DebugOut("Longueur" & @TAB & @TAB & @TAB & StringLen($fileVar) & @TAB & @TAB & StringLen($litteral))
_DebugOut("Longueur Cast" & @TAB & @TAB & StringLen($fileVar_Cast) & @TAB & @TAB & StringLen($litteral_Cast))
_DebugOut("Binaire" & @TAB & StringToBinary($fileVar) & @TAB & StringToBinary($litteral))
_DebugOut("Binaire Cast" & @TAB & @TAB & StringToBinary($fileVar_Cast) & @TAB & StringToBinary($litteral_Cast))
_DebugOut("Valeur" & @TAB & @TAB & @TAB & $fileVar & @TAB & @TAB & $litteral)
_DebugOut("Valeur Cast" & @TAB & @TAB & $fileVar_Cast & @TAB & @TAB & $litteral_Cast)
Code : Tout sélectionner
$fileVar $litteral
----------------------------------------------------------------------------------------------
IsString ? True True
IsString Cast ? True True
Chaîne == Cast ? False True
Variable == littéral ? False
Variable Cast == littéral Cast ? True
Variable Cast == littéral ? True
Longueur 12 4
Longueur Cast 4 4
Binaire 0x3F3F3F3F0000000000000000 0x3F3F3F3F
Binaire Cast 0x3F3F3F3F 0x3F3F3F3F
Valeur 高级搜索
Valeur Cast 高级搜索 高级搜索
Les binaires sont tous faux !
Mouais, il se passe de drôles de choses en UTF-8.
Demain, j'essaie l'UTF-16.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
- orax
- Modérateur

- Messages : 1479
- Enregistré le : lun. 23 mars 2009 04:50
- Localisation : ::1
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
En remplaçant FileRead() par FileReadLine() dans le code ci-dessus, ça marche. Hehe... 
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
- jchd
- AutoIt MVPs (MVP)

- Messages : 2283
- Enregistré le : lun. 30 mars 2009 22:57
- Localisation : Sud-Ouest de la France (43.622788,-1.260864)
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
On est déjà demain !
Bon, l'UTF-16 est plus cohérent :
Apparemment, pas besoin de "caster". Par contre, les binaires affichés partent tous en vrille (code de '?'). StringToBinary chercherait-il à interpréter ou ferait-il une conversion débile ???
J'y vois (un peu) plus clair. Les problèmes qui me restent, outre les fantisies de l'UTF-8, sont la conversion au vol des données entre des bases sous encodage distinct et l'affichage dans les GUI.
Pour les conversions, y aurait-il une autre voie que les _WinAPI_MultiByteToWideChar et inverse, car j'ai du mal a faire "entrer" ou "sortir" de l'UTF-16. D'ailleurs, l'interface me semble hermétique : string hexa enrobée dans une structure ??? Le core ferait-il une conversion dans notre dos ?
Bon, l'UTF-16 est plus cohérent :
Code : Tout sélectionner
$fileVar $litteral
----------------------------------------------------------------------------------------------
IsString ? True True
IsString Cast ? True True
Chaîne == Cast ? True True
Variable == littéral ? True
Variable Cast == littéral Cast ? True
Variable Cast == littéral ? True
Longueur 4 4
Longueur Cast 4 4
Binaire 0x3F3F3F3F 0x3F3F3F3F
Binaire Cast 0x3F3F3F3F 0x3F3F3F3F
Valeur 高级搜索 高级搜索
Valeur Cast 高级搜索 高级搜索
J'y vois (un peu) plus clair. Les problèmes qui me restent, outre les fantisies de l'UTF-8, sont la conversion au vol des données entre des bases sous encodage distinct et l'affichage dans les GUI.
Pour les conversions, y aurait-il une autre voie que les _WinAPI_MultiByteToWideChar et inverse, car j'ai du mal a faire "entrer" ou "sortir" de l'UTF-16. D'ailleurs, l'interface me semble hermétique : string hexa enrobée dans une structure ??? Le core ferait-il une conversion dans notre dos ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
- orax
- Modérateur

- Messages : 1479
- Enregistré le : lun. 23 mars 2009 04:50
- Localisation : ::1
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Je crois savoir pourquoi le code binaire retourné est mauvais : il faut mettre ", 4" à la fin StringToBinary($fileVar_Cast, 4) pour lui spécifier que le fichier est encodé en UTF-8 (voir aide).
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
- jchd
- AutoIt MVPs (MVP)

- Messages : 2283
- Enregistré le : lun. 30 mars 2009 22:57
- Localisation : Sud-Ouest de la France (43.622788,-1.260864)
- Status : Hors ligne
Re: [..] Chaînes en UTF-16 sous AutoIt v3.3.0 XP
Parfaitement exact !orax a écrit :Je crois savoir pourquoi le code binaire retourné est mauvais : il faut mettre ", 4" à la fin StringToBinary($fileVar_Cast, 4) pour lui spécifier que le fichier est encodé en UTF-8 (voir aide).
Au temps pour moi, j'ai occulté ce paramètre optionnel mais primordial ici.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
