Soutenez-nous
Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 8 sur 8
  1. #1
    Membre du Club
    Inscrit en
    août 2003
    Messages
    207
    Détails du profil
    Informations forums :
    Inscription : août 2003
    Messages : 207
    Points : 53
    Points
    53

    Par défaut Pos ou ansipos sur ansistring longueur > 255

    Bonjour à tous,

    J'utilise Delphi 2010 et je reçois d'une socket IP des données dont la longueur est d'environ 20 000 caractères UTF8.

    J'ai déclaré une variable XLMTextIN: RawByteString;

    Ensuite sur l'évevenement SocketServerClientRead
    je récupère les données reçues sur la socket

    XLMTextIN := Socket.ReceiveText;

    Pour info, XLMTextIN = '<?xml version="1.0" encoding="utf-8"?>....

    si je fais un pos('utf-8', XLMTextIN)
    ou ansipos('utf-8', XLMTextIN)

    la valeur renvoyée est toujours 0.

    Est ce parce que la longueur de XLMTextIN dépasse les 256 caractères ?
    Ou alors est ce pour une autre raison ?


    Merci d'avance pour vos réponses,
    Wilco

  2. #2
    Expert Confirmé Sénior
    Avatar de Paul TOTH
    Homme Profil pro Paul TOTH
    Freelance
    Inscrit en
    novembre 2002
    Messages
    5 337
    Détails du profil
    Informations personnelles :
    Nom : Homme Paul TOTH
    Âge : 44
    Localisation : Réunion

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 5 337
    Points : 13 903
    Points
    13 903

    Par défaut

    je ne sais pas où est l'erreur, mais pas dans la limite de taille, les string ne sont plus limité à 255 caractères depuis Delphi 2
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Produits : UPnP, RemoteOffice, FlashPascal
    Embarcadero : Ile de la Réunion, Dephi, C++Builder, RADPHP...TVA à 8,5%

  3. #3
    Expert Confirmé
    Avatar de Ph. B.
    Homme Profil pro Philippe
    Inscrit en
    avril 2002
    Messages
    1 137
    Détails du profil
    Informations personnelles :
    Nom : Homme Philippe
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2002
    Messages : 1 137
    Points : 3 024
    Points
    3 024

    Par défaut

    Bonjour,
    Citation Envoyé par Wilco Voir le message
    J'ai déclaré une variable XLMTextIN: RawByteString;
    ...
    si je fais un pos('utf-8', XLMTextIN)
    ...
    la valeur renvoyée est toujours 0.
    Il faudrait peut être convertir XMLTextIN en string avant de faire le test ?
    Philippe.

  4. #4
    Expert Confirmé Sénior Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    juillet 2006
    Messages
    9 939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juillet 2006
    Messages : 9 939
    Points : 12 777
    Points
    12 777

    Par défaut

    RawByteString est un type brut mais reste une AnsiString d'un point de vue mémoire

    je pense que c'est plus lié à un problème de conversion d'encodage !
    Quel variante utilise-t-il de Pos utilise-t-il ?

    Citation Envoyé par aide
    Code :
    1
    2
    3
    4
    function Pos(const SubStr, Str: ShortString): Integer;
    function Pos(const SubStr, Str: UnicodeString): Integer; overload;
    function Pos(const SubStr, Str: WideString): Integer; overload;
    function Pos(const SubStr, Str: RawByteString): Integer; overload;
    tu passes un UnicodeString et RawByteString
    du coup il doit avoir des difficultés pour choisir entre la variante 2 UnicodeString ou 2 RawByteString

    essaye ceci

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var 
      XLMTextIN: RawByteString;
    const
      XML_ENCODE:RawByteString = 'utf-8'; // force le typage et donc le choix de la variante
    begin
      index := Pos(XML_ENCODE, XLMTextIN);
      if index > 0 then
        ...
     
    end;
    ReceiveText d'un Socket retourne une AnsiString, c'est normalement théorique le plus proche du binaire avec un mode chaine

    As-tu essayé un ReceiveBuf dans TByteDynArray temporaire recopié ensuite dans un TMemoryStream pour finalement effectué un TXMLDocument LoadFromStream ?

    Pense aussi que tu ne recevra jamais les 20000 caractères d'un coup mais découpé en lot de 8Ko, il te faudra donc accumuler le XML dans le TMemoryStream, une fois complet, tu pourras le lire
    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

    Halte à la ségrégation des Cinémas, VO sur Paris, VF en Banlieue, Abonnement résilié !

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    septembre 2008
    Messages
    3 184
    Détails du profil
    Informations forums :
    Inscription : septembre 2008
    Messages : 3 184
    Points : 4 959
    Points
    4 959

    Par défaut

    Il faudrait déjà s'assurer qu'il n'y a pas de #0 dans la chaîne. Ceci permettrait de le contrôler :
    Code :
    ShowMessage(PAnsiChar(XLMTextIN) +#13 +IntToStr(Length(XLMTextIN)));
    Si la longueur du texte affiché ne correspond pas à la taille renvoyée, il y a un #0

  6. #6
    Membre du Club
    Inscrit en
    août 2003
    Messages
    207
    Détails du profil
    Informations forums :
    Inscription : août 2003
    Messages : 207
    Points : 53
    Points
    53

    Par défaut

    Merci à tous pour vos réponses ... J'ai peut être une explication sur le problème que je rencontre.

    J'utilise un TServerSocket et lorque la socket reçoit environ 20Ko de données, effectivement elle les reçoit en plusieurs paquets.

    J'ai mis un point d'arrêt sur l'évènement OnRead de la socket.

    Lors du 1er arrêt, si je consulte la variable
    XLMTextIN = Socket.ReceiveText; elle affiche bien '<?xml version="1.0" encoding="utf-8"?>.. je vois donc son contenu

    la seconde variable est :
    x := ansipos('utf-8', XLMTextIN);

    A ce moment, x = 0 ( ce qui est perturbant car il devrait afficher 31 )

    Et ce n'est qu'au 4ème passage sur le point d'arrêt que x = 31.

    Comme le dit justement Shail, les données n'arrivent pas en une seule fois et il semblerait que la fonction pos et/ou ansipos ne renvoie pas la bonne valeur tant que l'intégralité des données aient été reçues. C'est étrange car lors de chaque passage au point d'arrêt, le contenu de la variable XLMTextIN, qui reçoit les données de la socket, est bien visible.

    Au final j'arrive à faire fonctionner ce programme mais le débogage n'est pas facilité en raison du comportement soit de Delphi soit de mon application.


    Merci encore une fois à tous ceux qui ont apporté leur contribution à ce post.

    Wilco

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    septembre 2008
    Messages
    3 184
    Détails du profil
    Informations forums :
    Inscription : septembre 2008
    Messages : 3 184
    Points : 4 959
    Points
    4 959

    Par défaut

    Je ne fais que lire l'aide :

    La déclaration de variables ou de champs de type RawByteString doit être rarement effectué car cela peut conduire à un comportement indéterminé et à des pertes de données potentielles.
    Peut-être serait-il temps d'essayer un autre type...

  8. #8
    Expert Confirmé Sénior
    Avatar de Paul TOTH
    Homme Profil pro Paul TOTH
    Freelance
    Inscrit en
    novembre 2002
    Messages
    5 337
    Détails du profil
    Informations personnelles :
    Nom : Homme Paul TOTH
    Âge : 44
    Localisation : Réunion

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 5 337
    Points : 13 903
    Points
    13 903

    Par défaut

    RawByteString ne perd pas réellement de données, il perd sa page de code, du code le caractère #145 n'est pas forcément le caractère "æ", mais #65 sera toujours un "A"

    pour identifier clairement le problème en mettant de côté le debugueur j'utilise souvent une méthode très efficace:
    Code :
    1
    2
    3
    4
    5
    6
     
      {$IFDEF BUG}
       AllocConsole; // ouvre une console si elle n'existe pas déjà
       WriteLn('XLMTextIN = ', XLMTextIN, ' (', Length(XLMTextIN),')');
       WriteLn('Pos(utf-8)=', Pos('utf-8', XLMTextIN));
      {$ENDIF}
    en plaçant ce code juste avant ou après le Pos() qui pose problème on voit clairement ce qu'il se passe.

    ensuite on peut aller plus loin
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
     
      {$IFDEF BUG}
       AllocConsole; // ouvre une console si elle n'existe pas déjà
       if Length(XMLTextIn) >= 31 then
       begin
         WriteLn('XLMTextIN[31+] = ', Copy(XLMTextIN,31, MaxInt));
       end;
      {$ENDIF}
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Produits : UPnP, RemoteOffice, FlashPascal
    Embarcadero : Ile de la Réunion, Dephi, C++Builder, RADPHP...TVA à 8,5%

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •