[R] Chaînes en UTF-16 sous AutoIt v3.3.0 XP

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
Avatar du membre
jchd
AutoIt MVPs (MVP)
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

#1

Message par jchd »

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 ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
orax
Modérateur
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

#2

Message par orax »

jchd a écrit :Ainsi StringLen renvoie la longueur en _octets_ d'une chaîne UTF-8 au lieu de sa longueur en _caractères_.
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...

Code : Tout sélectionner

StringLen(String($CARACTERES_UTF8))
A propos, concernant sa limitation au niveau de l'Unicode, il y a une page dans l'aide à : Autoit \ Using Autoit \ Unicode Support.
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)
Avatar du membre
jchd
AutoIt MVPs (MVP)
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

#3

Message par jchd »

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...

Code : Tout sélectionner

StringLen(String($CARACTERES_UTF8))
A propos, concernant sa limitation au niveau de l'Unicode, il y a une page dans l'aide à : Autoit \ Using Autoit \ Unicode Support.
Et éventuellement placez un bout de code pour démontrer le reste du message.
De pénibles essais démontrent le contraire, pourtant. Que mets-tu dans $CARACTERES_UTF8 ?

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 d'un source stocké en UTF-8, le caractère Euro ne s'affiche pas correctement, le code est bien 0xE282AC, mais la longueur est 3 !
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
 
Effectivement et contrairement aux conseils d'utilisation de Send() figurant dans l'aide, cette fonction ne permet pas l'envoi de chaînes UTF-*. La doc est fausse sur ce point.

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é.
Avatar du membre
orax
Modérateur
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

#4

Message par orax »

De pénibles essais démontrent le contraire, pourtant. Que mets-tu dans $CARACTERES_UTF8 ?
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 :

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)
Avatar du membre
jchd
AutoIt MVPs (MVP)
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

#5

Message par jchd »

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.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
orax
Modérateur
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

#6

Message par orax »

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)
Avatar du membre
orax
Modérateur
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

#7

Message par orax »

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)
Avatar du membre
jchd
AutoIt MVPs (MVP)
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

#8

Message par jchd »

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.

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)

 
Ce qui produit :

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             高级搜索        高级搜索
 
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.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
orax
Modérateur
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

#9

Message par orax »

En remplaçant FileRead() par FileReadLine() dans le code ci-dessus, ça marche. Hehe... :P
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
Avatar du membre
jchd
AutoIt MVPs (MVP)
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

#10

Message par jchd »

On est déjà demain !

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                               高级搜索                高级搜索
 
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 ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
orax
Modérateur
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

#11

Message par orax »

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)
Avatar du membre
jchd
AutoIt MVPs (MVP)
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

#12

Message par jchd »

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).
Parfaitement exact !

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é.
Répondre