IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Windows Forms Discussion :

fichier non unicode


Sujet :

Windows Forms

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut fichier non unicode
    Bonjour,

    De retour de vacances, on me demande de reproduire en C# une procédure basée sur un code Delphi win32.
    Cette procédure remplit remplit une structure avec des membres de différents types, dont des string, et sauve la structure dans un fichier. Exemple de structure:

    Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {$ALIGN OFF} 
    TInfoHeader = record
      ID      : Word;
      Release : Integer;
      Code    : packed array[0..MAXLEN_CODE - 1] of char;   
    end;

    La structure est sauvée ensuite dans un fichier par l'intermédiaire d'un stream.

    Delphi 6 ne gérant pas l'unicode à ce niveau, je me dis que traduire simplement le code ne suffira pas. En effet, ma procédure en C# doit générer strictement le même fichier qu'en Delphi, et C# va me faire de l'unicode (enfin, si j'ai bien tout compris).

    J'ai donc pris le parti d'ouvrir directement un stream sur un fichier et d'écrire chaque valeur les une derrière les autres plutôt que de passer par une structure intermédiaire.

    Là, plusieurs questions:

    1) Le code suivant va t-il me générer un fichier compatible ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    FileStream stream = new FileStream(Fichier, FileMode.CreateNew);
    BinaryWriter writer = new BinaryWriter(stream);
     
    writer.Write(valeurEntiere);
    WriteToStream(writer, Name, MAXLEN_NAME);
     
    writer.Close();
    stream.Close();
    2) La procédure WriteToStream est codée ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void WriteToStream(BinaryWriter w, string text, int len)
    {
        byte[] arr = new byte[len];
        //
        w.Write(arr);
    }
    A la place du commentaire, que faut-il que j'ajoute pour écrire text au début du tableau ? (plus précisément, pour que les caractères de text soit placé dans les x premiers éléments du tableau)

    3) Dans le code ci-dessus, la ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    byte[] arr = new byte[len];
    assure t-elle que chaque élément de arr est bien initialisée à '' ?

    Merci d'avance de votre aide,

    Papy

  2. #2
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    SUITE ...

    Je viens de modifier ma procédure comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void WriteToStream(BinaryWriter w, string text, int len)
    {
        w.Write(Convert.ToString(text, UTF8Encoding.UTF8));
        byte[] t = new byte[len - text.Length];
        w.Write(t);
    }
    ça me semble mieux ... votre avis svp ?

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    C# va me faire de l'unicode (enfin, si j'ai bien tout compris).
    Pas forcément, ça dépend quel encodage tu utilises. Tu confonds avec la représentation interne des chaines .NET, qui est effectivement en Unicode.

    J'ai pas compris exactement ce que tu cherches à faire... tu veux écrire les données dans un fichier binaire, ou un fichier texte ?

  4. #4
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    D'abord, merci pour les balises de code ...

    Je vais essayer d'éclaircir tout ça.
    Nous avons 2 applications complémentaires écrites en delphi Win32.
    Chacune de ces applications utilise la même classe qui enregistre dans une structure (record), des informations de différents types (word, smallint, double, array of char de taille fixe). Cette structure peut être enregistrée dans un fichier binaire via un filestream. Quand la version d'un de ces 2 outils enregistre ses données dans un fichier, le fichier généré fait 3094 octets.

    Une de ces 2 applications doit être passée en C#. Le code doit donc générer un fichier totalement compatible. J'ai écris le code suivant:

    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
     
     
            void WriteToStream(BinaryWriter w, string text, int len)
            {
                String s = String.IsNullOrEmpty(text) ? "" : text;
                w.Write(s);
                byte[] t = new byte[len - s.Length];
                w.Write(t);
            }
     
            public static double ToDouble(DateTime what)
            {
                return BitConverter.ToDouble(BitConverter.GetBytes(what.Ticks), 0);
            }
     
            public bool Save()
            {
     
                FileStream stream = new FileStream(Fichier, FileMode.Create);
                BinaryWriter writer = new BinaryWriter(stream);
     
                System.UInt16 zero = 0;
                System.UInt16 one = 1;
                System.UInt16 two = 2;
     
                writer.Write(INFOEX_ID);
                writer.Write(INFOEX_RELEASE_140);
                WriteToStream(writer, PatientId, MAXLEN_PATIENT_ID);
                WriteToStream(writer, PatientLastName, MAXLEN_PATIENT_LASTNAME);
                WriteToStream(writer, PatientFirstName, MAXLEN_PATIENT_FIRSTNAME);
                WriteToStream(writer, PatientLastName2, MAXLEN_PATIENT_LASTNAME2);
                writer.Write(ToDouble(PatientDob));
                switch (PatientSex)
                {
                    case InfoexSex.sexMale:
                        writer.Write(one);
                        break;
                    case InfoexSex.sexFemale:
                        writer.Write(two);
                        break;
                    default:
                        writer.Write(zero); /*  InfoexSex.sexUnspecified  */
                        break;
                }
                writer.Write(PhysicianId);
                WriteToStream(writer, DeviceCode, MAXLEN_DEVICE_CODE);
                WriteToStream(writer, DeviceSerialNumber, MAXLEN_DEVICE_SERIAL_NUMBER);
                writer.Write(ExamType);
                writer.Write(ExamIsNew ? one : zero);
                writer.Write(ExamIsSigned ? one : zero);
                WriteToStream(writer, PhysicianSignature, MAXLEN_PHYSICIAN_SIGNATURE);
                WriteToStream(writer, ExamIndication, MAXLEN_EXAM_INDICATION);
                WriteToStream(writer, ExamMedication, MAXLEN_EXAM_MEDICATION);
                writer.Write(ToDouble(ExamDate));
                WriteToStream(writer, ExamDiagnosis, MAXLEN_EXAM_DIAGNOSIS);
                writer.Write(DeviceType);
                WriteToStream(writer, PatientAddress, MAXLEN_PATIENT_ADDRESS);
                WriteToStream(writer, PatientZip, MAXLEN_PATIENT_ZIP);
                WriteToStream(writer, PatientState, MAXLEN_PATIENT_STATE);
                WriteToStream(writer, PatientCity, MAXLEN_PATIENT_CITY);
                WriteToStream(writer, PatientPhone1, MAXLEN_PATIENT_PHONE1);
                WriteToStream(writer, PatientPhone2, MAXLEN_PATIENT_PHONE2);
                WriteToStream(writer, PatientFax, MAXLEN_PATIENT_FAX);
                WriteToStream(writer, PatientEmail, MAXLEN_PATIENT_EMAIL);
                writer.Write(ToDouble(SignatureDate));
     
                writer.Close();
                stream.Close();
    Bien sur, j'ai pris garde à utiliser des types de données compatibles entre eux.
    Pour le vérifier, j'ai additionné les tailles de chaque variable utilisée. Le résultat coté C# me donne bien 3094, ce qui tendrait à confirmer que l'ensemble des données à enregistrer coté c# donnera bien le même fichier résultat qu'avec la version Delphi.

    Problème: le fichier généré fait 3113 octets. Du coup, je cherchais du coté de l'encodage des caractères qui pourrait poser problème. A la ligne

    BinaryWriter writer = new BinaryWriter(stream);

    j'ai essayé l'encodage ASCII et UTF8, mais ça ne change rien.

    Le problème de différence de taille au final viendrait donc d'ailleurs. Mais je ne sais pas d'où.

    Qu'est-ce que C# peut bien ajouter dans le fichier pour créer cette différence de taille de 19 octets par rapport à la taille des données initiales ?

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Je crois que je vois où est le problème, ou au moins une partie :

    BinaryWriter.Write
    Citation Envoyé par MSDN
    Écrit dans ce flux une chaîne préfixée par sa longueur dans le codage actuel de BinaryWriter et avance la position actuelle du flux en fonction du codage utilisé et des caractères spécifiques écrits dans le flux.
    Donc ça n'écrit pas que les données de la chaine, mais aussi la longueur de cette chaine, sur 4 octets. Ce qui explique la taille plus importante du fichier. Par contre le compte n'y est pas... tu utilises 18 fois la méthode WriteToStream, ce qui devrait te faire 3094 + 4*18 = 3166, et non 3113...
    Donc il doit y avoir d'autres champs "sous-dimensionnés". Il faut que tu vérifies que les tailles des champs correspondent bien dans le code Delphi et le code C#.

    Pour écrire les chaines je te conseille de faire plutôt comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            void WriteToStream(BinaryWriter w, string text, int len)
            {
                String s = (text ?? "").PadLeft(len);
                byte[] bytes = Encoding.ASCII.GetBytes(s);
                w.Write(bytes);
            }

  6. #6
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    Merci pour le code ! Je ne connaissais pas encore le ?? ni PadLeft , très utiles.

    J'avais effectivement aussi un problème sur un autre type. C'est réglé.
    Me reste à tester la relecture par la version Delphi et ensuite faire la procédure Load.

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

Discussions similaires

  1. Wget - télécharger des fichiers non-html
    Par narmataru dans le forum Réseau
    Réponses: 10
    Dernier message: 14/07/2018, 15h20
  2. [ifstream] pb lecture fichier non sequentielle
    Par bludo dans le forum SL & STL
    Réponses: 3
    Dernier message: 10/02/2005, 21h30
  3. Création version client - fichiers non trouvés
    Par Pascal dans le forum WinDev
    Réponses: 7
    Dernier message: 03/12/2004, 11h34
  4. [Debutant][Install][VS]erreur sur fichier non trouvé.
    Par silvermoon dans le forum DirectX
    Réponses: 4
    Dernier message: 16/07/2004, 20h59
  5. Réponses: 7
    Dernier message: 21/05/2004, 17h13

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