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

MFC Discussion :

Représentation mémoire d'un CString


Sujet :

MFC

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2005
    Messages : 222
    Par défaut Représentation mémoire d'un CString
    Bonjour,

    je souhaiterai connaitre la réprésentation mémoire d'un CString.

    Pourquoi ?

    Parceque j'ai besoin de lire des fichiers binaires contenant pêle-mêle des "long", des "int", et des "CString".

    Pour les "long", je lis 4 Octets. Pour les "int", 2 Octets.

    Mais pour les CString ???
    J'ai compris que le premier octets était la taille du CString (mais quid d'un CString de plus 256 caractères ?)
    Ensuite les données sur autant d'octets que donnés par le premier Octet.

    Sauf que, si mon CString est une chaine vide ? Qu'ai-je ? Un "0" sur le premier octet, mais ai-je un deuxième octet ?

    Bref, je m'embrouille un peu, et quelques éclaircissement sur la représentation mémoireds'un CString m'aiderai bien.

    Pour info, les fichiers sont créés par la classe CArchive dans lequel on écrit avec l'opérateur surchargé "<<".
    Par contre, j'utilise un autre langage (le PHP) pour relire "octet par octet" ce fichier..

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Bonjour,
    J'ai moi aussi regardé comment la CString est sérialisée ou désérialisée par la classe CArchive, et j'ai fait cette classe en C#, tu peux peut-être t'en inspirer:
    Code C# : 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
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    	/// <summary>
    	/// Class to handle serialization of Strings in the format of a MFC <c>CArchive</c>.
    	/// </summary>
    	static class MFCStringHelper
    	{
    		/// <summary>
    		/// Write a string in the format of a MFC <c>CArchive</c>.
    		/// </summary>
    		/// <param name="writer">[modif] Output stream writer.</param>
    		/// <param name="str">[in] String to write.</param>
    		public static void WriteMFCString(BinaryWriter writer, String str)
    		{
    			if(writer==null)
    				throw new ArgumentNullException("writer");
    			if(str==null)
    				throw new ArgumentNullException("str");
    			AfxWriteStringLength(writer, str.Length, true);
    			writer.Write(str.ToCharArray());
    		}
     
    		/// <summary>
    		/// Read a string from the format of a MFC <c>archive</c>.
    		/// </summary>
    		/// <param name="reader">[in/modif] Input stream reader.</param>
    		/// <returns>String freshly read.</returns>
    		public static String ReadMFCString(BinaryReader reader)
    		{
    			if(reader==null)
    				throw new ArgumentNullException("reader");
     
    			int charSize;
    			long qwLength = AfxReadStringLength(reader, out charSize);
    			int length = checked((int)qwLength);
    			String sRet = null;
    			if(charSize==1)
    			{
    				//Read ANSI chars and convert
    				byte[] mbChars = reader.ReadBytes(length);
    				sRet = Encoding.Default.GetString(mbChars);
    			}
    			else
    			{
    				//Read unicode chars.
    				char[] wideChars = reader.ReadChars(length);
    				sRet = new String(wideChars);
    			}
    			Debug.Assert(sRet!=null, "The return string shall not be null at this point");
    			return sRet;
    		}
     
    		/// <summary>
    		/// Write a string length in the format of a MFC <c>CArchive</c>.
    		/// </summary>
    		/// <remarks>This code was converted from MFC source code file <c>arccore.cpp</c>.</remarks>
    		/// <param name="ar">[modif] Output stream writer.</param>
    		/// <param name="nLength">[in] Length to write.</param>
    		/// <param name="bUnicode">[in] if <c>true</c>, prepend with a "unicode" tag.</param>
    		static void AfxWriteStringLength(BinaryWriter ar, long nLength, bool bUnicode)
    		{
    			Debug.Assert(ar != null, "ar is an internal parameter and shall not be null");
    			Debug.Assert(nLength >=0, "String length shall not be negative");
     
    			if(bUnicode)
    			{
    				// Tag Unicode strings
    				ar.Write((Byte)0xFF);
    				ar.Write((UInt16)0xFFFE);
    			}
     
    			if(nLength < 255)
    			{
    				ar.Write((Byte)nLength);
    			}
    			else if(nLength < 0xFFFE)
    			{
    				ar.Write((Byte)0xFF);
    				ar.Write((UInt16)nLength);
    			}
    			else if(nLength < 0xFFFFFFFF)
    			{
    				ar.Write((Byte)0xFF);
    				ar.Write((UInt16)0xFFFF);
    				ar.Write((UInt32)nLength);
    			}
    			else
    			{
    				ar.Write((Byte)0xFF);
    				ar.Write((UInt16)0xFFFF);
    				ar.Write((UInt32)0xFFFFFFFF);
    				ar.Write((UInt64)nLength);
    			}
    		}
     
    		/// <summary>
    		/// Read a string length from the format of a MFC <c>archive</c>.
    		/// </summary>
    		/// <remarks>This code was converted from MFC source code file <c>arccore.cpp</c>.</remarks>
    		/// <param name="ar">[in/modif] Input stream reader.</param>
    		/// <param name="nCharSize">[out] Character size (1 or 2 bytes).</param>
    		/// <returns>String length.</returns>
    		static long AfxReadStringLength(BinaryReader ar, out int nCharSize)
    		{
    			Debug.Assert(ar != null, "ar is an internal parameter and shall not be null");
     
    			UInt64 qwLength;
    			UInt32 dwLength;
    			UInt16 wLength;
    			Byte byLength;
     
    			nCharSize = 1;
     
    			// First, try to read a one-byte length
    			byLength = ar.ReadByte();
    			if(byLength < 0xFF)
    				return byLength;
     
    			// Try a two-byte length
    			wLength = ar.ReadUInt16();
    			if(wLength == 0xFFFE)
    			{
    				// Unicode string.  Start over at 1-byte length
    				nCharSize = 2;
     
    				byLength = ar.ReadByte();
    				if(byLength < 0xFF)
    					return byLength;
     
    				// Two-byte length
    				wLength = ar.ReadUInt16();
    				// Fall through to continue on same branch as ANSI string
    			}
    			if(wLength < 0xFFFF)
    				return wLength;
     
    			// 4-byte length
    			dwLength = ar.ReadUInt32();
    			if(dwLength < 0xFFFFFFFF)
    				return dwLength;
     
    			// 8-byte length
    			qwLength = ar.ReadUInt64();
    			if(qwLength > Int32.MaxValue)
    				throw new FormatException("String too long");
    			return checked((long)qwLength);
    		}
    	}
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Donc tu vois, le premier octet n'est la longueur de la chaîne que si celle-ci fait moins de 255 caractères et n'est pas en unicode (UCS-2 ou UTF-16).
    Si la chaîne fait 255 caractères ou plus, ou si elle est unicode (UCS-2 ou UTF-16), le premier octet sera 0xFF et ainsi de suite.

    Et le caractère nul n'est pas enregistré.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    Salut,
    la CString est capable de contenir des données binaires (donc int et compagnie)
    en utilisant par exemple le constructeur spécifiant un buffer et une longueur.
    la méthode GetLenght() renvoie la taille stockée.
    si bien que l'on peut très bien avoir une chaine avec le premier octet à zéro et quelque chose derrière.
    il ne faudra donc pas tomber dans le piège d'utiliser strlen sur une CString
    mais bien GetLength() pour sa longueur.
    utiliser CArchive pour constituer un fichier binaire n'est pas une bonne idée,
    CArchive sert a la sérialisation des données et inscrit donc dans le flux des informations relatives aux objets.
    il vaudrait mieux utiliser un CFile en mode Binaire.

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Mais la classe CArchive ne sert-elle pas justement à écrire des objets MFC dans le CFile ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Représentation mémoire tableau 2 dimensions
    Par stoner dans le forum Débuter
    Réponses: 5
    Dernier message: 16/04/2013, 20h52
  2. [RPG] Déroulement du jeu : comment le représenter en mémoire ?
    Par TheDrev dans le forum Développement 2D, 3D et Jeux
    Réponses: 1
    Dernier message: 31/08/2009, 20h20
  3. Représentation d'un PIC X(2) en mémoire
    Par Kirou dans le forum Cobol
    Réponses: 7
    Dernier message: 13/03/2009, 13h48
  4. CString et fuite mémoire
    Par r0d dans le forum MFC
    Réponses: 9
    Dernier message: 23/02/2006, 19h41
  5. Réponses: 1
    Dernier message: 02/12/2005, 14h18

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