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

Discussion: Sérialisation et accents français [Lazarus]

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut Sérialisation et accents français

    J'ai rencontré deux problèmes avec la sérialisation en mode texte. Le premier concerne l'encodage des caractères accentués et le second le type TDate.

    L'encodage des caractères accentués est complètement corrompu dans le fichier de sérialisation. Voici le début du fichier de sérialisation qui ne se désérialise pas convenablement. Utiliser ou ne pas utiliser {$codepage utf8} n'a aucun effet sur le problème: le test unitaire foire en raison de l'encodage. Un ShowMessage confirme l'erreur d'encodage après la désérialisation. String, AnsiString ou UnicodeString, n'a aucune incidence sur le problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    object TInfoDeBaseTournoi
      SerializeInfoDeBaseTournoi = (
        'Championnat Ouvert du Qu'#195#169'bec'
        'Montr'#195#169'al'
        'e:\bozo\le\Clown\'
    Deuxième problème, WriteDate déclenche une exception lors de l'écriture de la date. Je peux contourner ce problème en transformant la date en chaîne de caractères en utilisant DateToStr.
    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
     
    procedure TInfoDeBaseTournoi.WriteInfo(Writer: TWriter);
       begin
          with Writer do begin
            WriteListBegin;
            WriteString(NomDuTournoi_A);
            WriteString(LieuDuTournoi_A);
            WriteString(CheminVersCeTournoi_A);
            WriteString(NomDelArbitrePrincipal_A);
            //WriteDate(DateDuDebut_A);
            WriteString(DateToStr(DateDuDebut_A));
            //WriteDate(DateDeLaFin_A);
            WriteBoolean(LeTournoiEstTermine_A);
            WriteInteger(NombreDeSections_A);
            //WriteDate(DateDeLaCreation_A);
            WriteListEnd;
     
          end;
    La sérialisation binaire des caractères accentués et des dates ne cause aucun problème. Cela me laisse perplexe, est-ce un bogue ?
    Images attachées Images attachées  

  2. #2
    Membre émérite
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 102
    Points : 2 892
    Points
    2 892
    Billets dans le blog
    2

    Par défaut

    Salut

    Utilises tu la méthode "DefineProperties(aFiler: TFiler);" dans ton composant ?
    Un autre chose pourquoi utilses tu "WriteListBegin/WriteListEnd;" ce n'est pas une liste (TStrings ou autre) et la dedans, il ne faut que des variables de même type (c'est mieux, cela pourrait-être un objet persistant, regroupant toutes tes infos) Donc essayes en enlevant ces références.

    Pour plus de simplicité publies simplement tes propriétés dans "published" et tu n'auras pas a utiliser TWriter/TRead

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  3. #3
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut

    Mon DefineProperties est bien présent. J'utilise TWriter quand la classe renferme des données non-modifiables, dans le cas présent, la date de création du tournoi. Il ne suffit pas de publier les propriétés afin de pouvoir sérialiser, il faut qu'elles soient accessibles en lecture et en écriture, ce qui pourrait violer des contraintes d'intégrités.

    D'après la définition, TWriter.WriteListBagin écrit un indicateur de début dans le stream https://www.freepascal.org/docs-html...listbegin.html.

  4. #4
    Membre émérite
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 102
    Points : 2 892
    Points
    2 892
    Billets dans le blog
    2

    Par défaut

    Si tes données sont en lecture seule , tu entres ces valeurs dans le Constructor Create de ton composant et tu ne met pas de "Write" dans "property" basta, pourquoi vouloir sauvegarder des données qui sont non modifiables ??? je pige pas bien ta démarche.
    Et niveau intégrité ce n'est pas le fait de sérialiser ces infos qui va te protéger surtout lors du développement Le but c'est surtout que l'utilisateur final de ton application ne puisse pas modifier certaines informations, non ?
    Tu ne va pas recompiler ton appli à chaque fois que tu veux rajouter un tournoi ? si ? Je ne comprend pas bien ???

    Si tes propriété ne sont pas publiées (dans published) elles doivent quand même apparaitre quelques part (dans public ou protected) De plus à mon sens tu n'a pas qu'un seul tournoi ? si ? donc à mon avis c'est ton approche du problème qu'il faudrait revoir.

    From scratch, vite fait (mais je ne vois pas l'intérêt de faire comme cela ) :

    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
    Type
      TInfoTournoi = Class(TPesistent)
      private
         FNom : String;
         FDateDebut : TDate;
     
         function GetDateDebut : TDate;
         procedure ReadDateDebut(TReader : TReader);  // /!\ DEFINIR UN TREADER/TWRITER PAR PROPRIETE, ELLES NE SONT PAS DES LISTES OU UN RECORD
         procedure WriteDateDebut(TReader : TReader);
      protected
         property InternalDateDebut : TDate read FDateDebut write FDateDebut;
         procedure Defineproperties(Filer : TFiler); override;  
    public
       procedure SetDateDebut(Value : TDate);
    published
     
        property DateDebut : TDate read GetDateDebut;
        property Nom : String read FNom write FNom
      end;
    Pourrais tu expliquer un peu plus ce que tu souhaites réaliser avec ton application et expliques nous plus en profondeur ta démarche de code. (Un bout de code, pourrait aussi mieux nous éclairer )

    Bonne journée
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut

    Merci BeanzMaster!

    Cette classe ne se sérialise pas convenablement par défaut sans TWriter et TReader.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TInutile = class(TComponent)
        public
          Constructor Create (const x1,y1:Integer);
        private
          X_A,Y_A: Integer;
        published
          property X: Integer read X_A write X_A;
          property Y: Integer read y_A;
      end;
    Voici le fichier de sérialisation en mode texte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    object TInutile
      X = -4
    end
    Le système de sérialisation réalise qu'il serait impossible de désérialiser Y sans accès en écriture et exclut cette propriété de la sérialisation. Le système de test unitaire de Lazarus indique clairement qu la propriété Y n'a pas été désérialisée et que sa valeur initiale de 0 est demeurée inchangée.

    Revenons au problème original, la classe que j'essaie de sérialiser sera la classe de base utilisée dans une fabrique abstraite en vue de générer un logiciel permettant la gestion de tournois. Il s'agit d'un framework qu'il faudra spécialiser pour les tournois, de tarot, d'échecs, de bridge de belote, de dames... La classe TInfoDeBaseTournoi représente de l'information statique (qui ne devrait pas être modifiée durant la compétition) à propos du tournoi. Le but de la conception est d'extraire ce qui est commun à tous les tournois et de le mettre dans cette classe dont on pourra hériter pour créer un tournoi concret. C'est une sous-classe de TComponent afin que l'on puisse l'attacher à un parent et que ce dernier soit responsable de sa destruction.

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    unit InfoDeBaseTournoi;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils;
     
    TYPE
      //L'information de base à propos de tous les tournois
      //L'infomation dans les attributs proviendra d'un formulaire rempli par l'utilisateur
      //On ne peut pas la valider ni à priori, ni une ligne à la fois car la combinaison
      //d'attibuts de ce formulaire avec ceux d'une sous-classe concrète pourrait
      //violer les contraintes d'intégrité.
     
      TInfoDeBaseTournoi = class (TComponent)
        Public
          Constructor Create(aowner: TComponent); override;
          Destructor Destroy; override;
     
          procedure Valider virtual; abstract;
        published
          procedure DefineProperties(Filer: TFiler); override;
        public
          procedure ReadInfo(Reader: TReader); virtual;
          procedure WriteInfo(Writer: TWriter); virtual;
     
        Strict Private
          NomDuTournoi_A, LieuDuTournoi_A,
          CheminVersCeTournoi_A,
          NomDelArbitrePrincipal_A : String;
          DateDuDebut_A, DateDeLaFin_A, DateDeLaCreation_A : TDate;
          LeTournoiEstTermine_A : Boolean;
          NombreDeSections_A:Integer;
     
        Public
           Property NomDuTournoi : String read NomDuTournoi_A write NomDuTournoi_A;
           Property LieuDuTournoi : String read LieuDuTournoi_A write LieuDuTournoi_A;
           Property CheminVersCeTournoi: String read CheminVersCeTournoi_A write CheminVersCeTournoi_A;
           Property NomDelArbitrePrincipal : String read NomDelArbitrePrincipal_A write NomDelArbitrePrincipal_A ;
           Property DateDuDebut : TDate read DateDuDebut_A write DateDuDebut_A;
           Property DateDeLaFin : TDate read DateDeLaFin_A write DateDeLaFin_A;
           Property LeTournoiEstTermine : Boolean read LeTournoiEstTermine_A write LeTournoiEstTermine_A;
           Property NombreDeSections : Integer read NombreDeSections_A write NombreDeSections_A;
           Property DateDeLaCreation: TDate read DateDeLaCreation_A;  //Aucun accès en écriture
     
      end;
     
    implementation
       Constructor TInfoDeBaseTournoi.Create(aowner: TComponent);
       begin
     
                DateDeLaCreation_A := Now;
                LeTournoiEstTermine_A := FALSE;
                NombreDeSections_A:=1;
         inherited ;
       end;
       Destructor TInfoDeBaseTournoi.Destroy;
       begin
          inherited;
       end;
       procedure TInfoDeBaseTournoi.DefineProperties(Filer: TFiler);
       begin
          inherited DefineProperties(Filer);
     
          Filer.DefineProperty('SerializeInfoDeBaseTournoi', @ReadInfo, @WriteInfo, TRUE);
       end;
       procedure TInfoDeBaseTournoi.ReadInfo(Reader: TReader);
       begin
          with Reader do begin
            ReadListBegin;
            NomDuTournoi_A:=ReadString;
            LieuDuTournoi_A:=ReadString;
            CheminVersCeTournoi_A:=ReadString;
            NomDelArbitrePrincipal_A:=ReadString;
            DateDuDebut_A:=ReadDate;
            DateDeLaFin_A:=ReadDate;
            LeTournoiEstTermine_A:=ReadBoolean;
            NombreDeSections_A:=ReadInteger;
            DateDeLaCreation_A:=ReadDate;
            ReadListEnd;
          end;
       end;
     
       procedure TInfoDeBaseTournoi.WriteInfo(Writer: TWriter);
       begin
          with Writer do begin
            WriteListBegin;
            WriteString(NomDuTournoi_A);
            WriteString(LieuDuTournoi_A);
            WriteString(CheminVersCeTournoi_A);
            WriteString(NomDelArbitrePrincipal_A);
            WriteDate(DateDuDebut_A);
            //WriteString(DateToStr(DateDuDebut_A));
            WriteDate(DateDeLaFin_A);
            WriteBoolean(LeTournoiEstTermine_A);
            WriteInteger(NombreDeSections_A);
            WriteDate(DateDeLaCreation_A);
            WriteListEnd;
          end;
       end;
     
    end.
    La sérialisation en mode binaire fonctionne comme un charme, mais j'ai une préférence pour celle en mode texte en raison de la grande facilité avec laquelle la corruption d'un fichier peut être corrigée par l'utilisateur.

    C'est certain qu'il va y avoir plusieurs tournois, chacun sauvegardé dans un chemin différent choisi par l'utilisateur.

  6. #6
    Membre émérite
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 102
    Points : 2 892
    Points
    2 892
    Billets dans le blog
    2

    Par défaut

    Bonjour, ok je cerne mieux ton projet.

    Pourquoi ne pas utiliser une base de donnée type SQLite par exemple ? .
    Autre solution plutôt que passer par les DefineProperties, TWriter/TReader (car je suppose que dans ton application finale tu utiliseras les méthodes Read/WriteComponent pour lire et enregistrer les tournois dans des fichiers)
    Une solution plus simple et rapide serait d'utiliser directement les flux (TFileStream) et d'ajouter des methode SaveToFile, LoadFromFile.

    Autre idée à essayer tout de même rajouter le mot-clef stored

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     published
          property X: Integer read X_A write X_A;
          property Y: Integer read y_A; Stored;
    Sinon la solution comme je le disait serai de passer par une propriété "protected" que j'ai donné plus haut et surcharger la méthode Loaded

    Bref, si nous reprenons le concept en gros. Que faut-il ?

    - Un objet de base dont chaque type de tournois disponible dans l'application (Belote, tarot, bridge etc...) (l'utilisateur ne pourras pas créer son propre type de tournois)
    - Une liste contenant tous les tournois (avec possibilité de filtrage par type de tournoi) ou une liste par type de tournois. A définir. ???

    Un des moyens simple serait l'utilisation de TCollection et TCollectionItem (https://stackoverflow.com/questions/...-serialization) ou juste une TList spécialisée avec des objets persistants (cf : http://www.atug.com/andypatterns/collections.htm)

    Il existe plusieurs façon de procéder. Et je pense que ton approche est trop compliquée a mettre en place pour pas grand chose. Car enfin de compte rien ne t'empêche de publier cette fameuse "Date de création" car dans ton application, au final si tu ne donnes pas la possibilité à l'utilisateur de modifié cette donnée, il ne pourra rien faire

    Donc à réfléchir pour le comment, a toi de voir la solution qui te conviendrait le mieux (à mon avis une TCollection ou une TList serait bien plus simple à gérer, à défaut d'une BDD)

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  7. #7
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    mars 2005
    Messages
    3 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : mars 2005
    Messages : 3 311
    Points : 9 559
    Points
    9 559
    Billets dans le blog
    6

    Par défaut

    Bonsoir,
    Ne peut-on imaginer que l'accesseur write soit défini mais que son traitement dépende d'une variable protégée initialisée True au Create et qu'elle passera False après l'avoir modifiée ?
    Delphi 5 Pro - Delphi 10.2 Tokyo Community Edition - CodeTyphon 6.50 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  8. #8
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut

    J'ai finalement découvert la nature du problème. Après vérification de ce qui était écrit dans le fichier de sérialisation, il est ressorti clairement que ce qui était écrit a été encodé en UTF8. D'autre part, la documentation officielle de Free Pascal indique clairement que sans la directive

    l'utilisation de constantes UnicodeString est fausse partout (Wrong everywhere). https://wiki.lazarus.freepascal.org/...d_string_types Évidemment, dans les tests unitaires, ce sont des constantes qui sont utilisées afin de vérifier le bon fonctionnement de la sérialisation.

    Pour sérialiser correctement une chaîne de caractères renfermant des accents français, il suffit d'ajouter cette directive dans chaque unités du programme et de modifier TWriter et TReader. Free Pascal offre la fonction ReadUnicodeString et WriteUnicodeString.

    Pour lire cela correctement,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    object TInfoDeBaseTournoi
      SerializeInfoDeBaseTournoi = (
        'Championnat Ouvert du Qu'#195#169'bec'
    il faut utiliser la fonction TWriter.ReadUnicodeString afin d’interpréter correctement #195#169 qui est le code Unicode pour é.

    J'ai aussi constaté que si on utilise des propriétés accessibles en lecture et en écriture avec le codepage précité, tout va bien.

    Heureusement que j'ai réalisé des tests unitaires, sans quoi ce problème aurait été détecté beaucoup plus tard.

    Les tests sont concluants, tant la classe de base que la sous-classe concrète ont été sérialisées sans problème.Cette dernière sérialisation comprend à la fois les données propres à la sous-classe et toutes celles de son parent.

    Merci encore BeanzMaster, vos suggestions ont été prises en compte, mais cette classe étant un quasi-singleton: une seule instance permise par tournoi, il est peu probable qu'elle évolue vers quelque chose de plus complexe que le WriteComponent actuel. Je vais conserver l'idée du SQLite ou de la version Embedded de FirebirdSQL pour les tables plus importantes, comme la liste des inscrits par exemple, qui pourrait dépasser 600 participants dans certains tournois. La nécessité de trier cette liste à la fois en ordre alphabétique et en ordre de têtes de séries milite en faveur d'une base de données bien indexée.

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut

    Citation Envoyé par tourlourou Voir le message
    Bonsoir,
    Ne peut-on imaginer que l'accesseur write soit défini mais que son traitement dépende d'une variable protégée initialisée True au Create et qu'elle passera False après l'avoir modifiée ?
    Cette façon de procéder permettrait d'éliminer le recours au TWriter et au TReader, qui étaient la cause réelle du problème avec le mauvais codepage.

    Si on veut vraiment protéger une variable contre l'écriture, il faut aussi normalement interdire l'utilisation du constructeur en tant que fonction normale, ce qui n'a pas encore été réalisé ici, mais qui a déjà été discuté dans ce forum. La démarche à accomplir est donc connue: il s'agit d'ajouter un booléen qui permet de déterminer si le constructeur est appelé sur une instance neuve ou sur une instance existante. Le même booléen pourrait servir à empêcher les modifications via les propriétés

  10. #10
    Responsable Pascal, Delphi et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    mars 2003
    Messages
    7 618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : mars 2003
    Messages : 7 618
    Points : 54 522
    Points
    54 522
    Billets dans le blog
    2

    Par défaut

    Bonjour,
    Citation Envoyé par Pierre le Grand Voir le message
    il est ressorti clairement que ce qui était écrit a été encodé en UTF8. D'autre part, la documentation officielle de Free Pascal indique clairement que sans la directive

    l'utilisation de constantes UnicodeString est fausse partout (Wrong everywhere). https://wiki.lazarus.freepascal.org/...d_string_types Évidemment, dans les tests unitaires, ce sont des constantes qui sont utilisées afin de vérifier le bon fonctionnement de la sérialisation.
    Attention, le type UnicodeString c'est de l'UTF-16, et tout littéral se trouvant dans le code source Lazarus est encodé en UTF-8.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]

  11. #11
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut

    Merci pour cette précision.

    {$codepage UTF8} modifie ce qui est écrit dans le fichier de texte. Sans cette directive, le mot « Québec » est encodé Qu'#195#169'bec et avec cette directive, il est encodé Qu'#233'bec. Le second encodage se désérialise sans problème.

    Je viens de découvrir une autre version surchargé de la procedure ObjectBinaryToText(Input, Output: TStream; Encoding: TObjectTextEncoding); qui ajoute un encodage qui est décrit ici https://www.freepascal.org/docs-html...tencoding.html .

  12. #12
    Membre régulier
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : février 2013
    Messages : 56
    Points : 114
    Points
    114

    Par défaut

    On peut obtenir un fichier de sérialisation complètement lisible en utilisant ObjectBinaryToText(OMStream,OFStream,oteLFM); . Plus besoin, ni d'UnicodeString, ni de WriteUnicodeString. ni de {codepage UTF8}.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    object TInfoDeBaseTournoi
      SerializeInfoDeBaseTournoi = (
        'Championnat Ouvert du Québec'

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Perl et les accents français!?!?
    Par CACI27 dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 12/04/2012, 11h17
  2. Les accents français en Ruby
    Par MarcRay dans le forum Ruby
    Réponses: 8
    Dernier message: 16/03/2012, 21h28
  3. Réponses: 2
    Dernier message: 05/01/2012, 10h08
  4. Accent français avec LIKE
    Par Erakis dans le forum Débuter
    Réponses: 2
    Dernier message: 09/11/2009, 19h40
  5. [firebird 1 et les accents français]
    Par Lucien dans le forum Débuter
    Réponses: 2
    Dernier message: 06/10/2005, 13h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo