Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Traitement unicode et Language europe de l'Est.


Sujet :

Langage Delphi

  1. #1
    Membre confirmé
    Traitement unicode et Language europe de l'Est.
    Bonjour à tous,

    J'ai une application qui a été développée avant la standardisation de l'Unicode dans delphi, et qui n'a connu que des langages latin ou anglo-saxon.
    Aujourd'hui on me demande de traiter du cyrillique. Grace aux évolutions de delphi (Unicode) dans ce domaine, il me semble que tous cela se passe bien en terme d'IHM (affichage dans les composants, copier/coller car j'ai pas de clavier pour tester, mais je suis confiant).

    Par contre pour les enregistrements ce n'est pas si simple. Ils existent pour typer les fichiers qui reçoivent ses informations. Et ce type d'enregistrement ne peut contenir que des ShortString?

    voici un exemple d'un des enregistrement
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Type
        Tabletransco = record
            ConFTypeCarte  : integer;
            ConFslot       : string[10];
            ConFabrevia    : string[10];
            ConFmax        : integer;
            ConFmin        : integer;
            ConFChampPt    : string[15];
            ConFcouleur    : Tcolor;
            Ptsys          : string[6];
            PtTmux         : string[10];
            Ptinter        : string[50];
            PtTrans        : string[50];
            Equi           : string[50];
            Info           : string[100];
     
            Ptcouleur: string[17];
        end;
     
    var
        info_transco: Tabletransco;
        FTrancodage: file of Tabletransco;



    Dans ces enregistrements, certaines variables de type "shortstring" reçoivent des textes en cyrillique, donc elles doivent savoir le gérer.

    Donc voici mes questions :

    1. J'ai du mal à m'y retrouver dans les différences entre UnicodeString, AnsiString, WideString et leur compatibilité.Comment convertir les "string[xx]" en Unicode ?

    Mes hypothèses :

    1. Changer dans l'enregistrement le type (short)string et UnicodeString, mais ce nouveau type sera t-il rétro-compatible avec mes anciens fichiers ? j'en doute !
    2. Créer un second enregistrement identique mais avec des strings Unicode et mettre en place le moyen d’identifier quel enregistrement des deux utiliser pour ouvrir le fichier visé ?
    3. d'autres solutions ?

    merci a vous .
    Bye et bon code...

    Ce n'est pas tant l'aide de nos amis qui nous aide , mais notre confiance dans cette aide .

  2. #2
    Membre expérimenté
    Bonjour

    La ligne
    FTrancodage: file of Tabletransco;
    rend ton code incompatible avec des mélanges entre Unicode / UTF-8 ou 16 et ANSI.

    Si tu utilises des chaînes dans tes RECORD tu fais en fait des tableaux de caractères qui correspondaient anciennement à des octets.

    1 caractère = 1 octet était valable en ANSI mais ne l'est plus en Unicode / UTF

    Et là où ça se complique c'est qu'un caractère peut-être de 1 à 4 octets selon l'encodage choisi.

    Il est donc à mon avis impératif pour toi de modifier la façon dont tu gères tes stockages de données si tu veux pouvoir y stocker autre chose que de l'ANSI

  3. #3
    Expert éminent sénior
    pour compléter la réponse de Patrick, les string[x] sont des ShortString, c'est à dire un tableau de x + 1 octets avec en position 0 la longueur utile de la chaîne.

    depuis 2009 les chaînes possèdent une page de code...mais pas les ShortString qui sont traitées systématiquement avec la page de code Windows en cours (1252 pour les français).

    du coup si tu utilises ton record sur un Windows Français c'est transparent, si tu utilises ton record sur un Windows en cyrillique, ça va aussi fonctionner, mais le fichier de l'un ne pourra pas être correctement lu par l'autre.

    si tu dois supporter les deux pages de codes dans la même appli, tu dois forcément modifier ton fichier (ou à défaut son nom) pour savoir quelle page de code est utilisée...ensuite tu peux jouer avec la variable DefaultSystemCodePage pour lire le fichier dans la bonne page de code, ou en passant par exemple par TMarshal.ReadStringAsAnsi.

    sinon il faut remplacer test "string[x]" par des "array[0..x-1] of Char", soit avec un #0 terminal, soit avec un champ longueur...mais ton fichier utilisera des Chars 16bits et ne sera pas compatible avec l'existant.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre confirmé
    bonjour a vous deux...

    Je m'attendais à vos réponses... mais au cas ou une astuce avait existé !!

    La solution que j'ai retenue est :

    1. Doubler tous mes "Record". On dira un ancien avec des chaines "AnsiString" et un nouveau avec des chaines "Unicode".
    2. Toutes les sauvegardes des fichiers seront faite à partir la version suivante et basées sur le nouveau Record (Unicode).
    3. Les anciens fichiers seront ouverts avec l'ancien "Record" compatibilité oblige, d’où la coexistence.
    4. Il me reste à arriver à détecter ou déterminer le type de fichier à l'ouverture, Unicode ou pas pour sélection le bon record. je peux en effet le traiter avec la date courante du logiciel
    Néanmoins , les fichiers peuvent se balader d'un pays à l'autre, donc pas optimal.

    voici mes nouvelles déclarations de Record:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    // exemple ancien type
    Type
        TableOldInfo = record
            Info1  : integer;
            Info2  : string[10];
    end;
    var
        Oldinfo: TableOldInfo;
        FOldInfo: file of TableOldInfo;
     
     
    // exemple nouveau type
    Type
        TableNewInfo = record
            Info1  : integer;
            Info2  : array [0..10] of WideChar;
    end;
    var
        Newinfo: TableNewInfo;
        FNewInfo: file of TableNewInfo;
     
    // ensuite lors de l'ecriture  
    StringToWideChar(TabInfo.cells[1,boucle], Newinfo.Info2,10);
     
    // et de la lecture  
    TabInfo.cells[1, boucle] := WideCharToString(NewInfo.Info);


    Cela semble fonctionner , est ce la bonne voie !! un conseil ..?

    Par contre je constate que dans cette instruction : StringToWideChar(TabInfo.cells[1,boucle], Newinfo.Info2,10), si ta taille de la chaine est égale ou supérieure au nombre d'élément du tableau de caractères, les 1er caractères ne sont pas rempli et le tableau reste vide.
    Je vais me pencher dessus.
    Bye et bon code...

    Ce n'est pas tant l'aide de nos amis qui nous aide , mais notre confiance dans cette aide .

  5. #5
    Membre expérimenté
    En fait, si tu en as techniquement la possibilité, je dirais qu'il vaudrait mieux éliminer les RECORD pour le stockage en fichier et passer par des bases SQL ou du stockage en JSON, ça te permettrait de t'épargner les soucis de stockage/conversion/etc.

    Dans Delphi tu peux modifier tes RECORD pour enlever la taille ce qui permettra de travailler en Unicode.

    Les seules procédures à modifier seraient le chargement et le stockage de tes fichiers et/ou leur parcourt selon comment tu gères ça. Le reste du code peut continuer de façon transparente à travailler sur les record, les accès fichiers feraient une conversion vers ton nouveau format de stockage à l'ouverture des fichiers existants puis tu travaillerais sur les nouveaux.

  6. #6
    Expert éminent sénior
    le BOM UTF8 ou UTF16 serait une bonne pratique pour vérifier le type de record à utiliser, plus fiable que le nom (ou extension) du fichier

    tu ne pourrais plus faire de file of TableOldInfo mais un TFileSteam et un Read, cela permettra de plus d'envisager une structure évolutive du fichier

    Attention à string[10] et array [0..10] of WideChar
    string est indicé de 1 à 10
    array est indicé de 0 à 9, le 10 DOIT être un Zéro terminal, ne pas oublier cela dans les manipulations, bien vérifier si les fonctions utilisent un count AVEC ou SANS le zéro terminal
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Expert éminent sénior
    sur les fichiers structurés il est aussi courant d'utiliser le premier record comme entête de fichier, c'est à dire que le premier enregistrement doit avoir exactement la même taille que le record, mais il contient des informations d'une autre nature : version du fichier, nombre d'enregistrements, adresse du premier supprimé...
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

###raw>template_hook.ano_emploi###