Précédent   Forum du club des développeurs et IT Pro > Environnements de développement > Delphi > Langage
Langage Tout ce qui concerne le langage (POO, syntaxe, message d'erreur...)
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 22/02/2013, 18h54   #1
Wilco
Membre du Club
 
Inscription : août 2003
Messages : 202
Détails du profil
Informations forums :
Inscription : août 2003
Messages : 202
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
Wilco est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2013, 19h33   #2
Paul TOTH
Expert Confirmé Sénior
 
Avatar de Paul TOTH
 
Homme Paul TOTH
Freelance
Inscription : novembre 2002
Messages : 4 544
Détails du profil
Informations personnelles :
Nom : Homme Paul TOTH
Âge : 43
Localisation : Réunion

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

Informations forums :
Inscription : novembre 2002
Messages : 4 544
Points : 11 931
Points : 11 931
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%
Paul TOTH est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2013, 22h50   #3
Ph. B.
Expert Confirmé
 
Avatar de Ph. B.
 
Homme Philippe
Inscription : avril 2002
Messages : 1 059
Détails du profil
Informations personnelles :
Nom : Homme Philippe
Âge : 46
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : avril 2002
Messages : 1 059
Points : 2 809
Points : 2 809
Envoyer un message via ICQ à Ph. B. Envoyer un message via Skype™ à Ph. B.
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.
Ph. B. est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 25/02/2013, 11h57   #4
ShaiLeTroll
Expert Confirmé Sénior
 
Avatar de ShaiLeTroll
 
Homme
Développeur C++\Delphi
Inscription : juillet 2006
Messages : 9 261
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 32
Localisation : France

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

Informations forums :
Inscription : juillet 2006
Messages : 9 261
Points : 13 373
Points : 13 373
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é !
ShaiLeTroll est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/02/2013, 13h20   #5
Andnotor
Rédacteur/Modérateur
 
Avatar de Andnotor
 
Inscription : septembre 2008
Messages : 2 886
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 2 886
Points : 4 372
Points : 4 372
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
__________________
Mes tutoriels Delphi
Andnotor est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/02/2013, 22h58   #6
Wilco
Membre du Club
 
Inscription : août 2003
Messages : 202
Détails du profil
Informations forums :
Inscription : août 2003
Messages : 202
Points : 53
Points : 53
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
Wilco est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/02/2013, 09h38   #7
Andnotor
Rédacteur/Modérateur
 
Avatar de Andnotor
 
Inscription : septembre 2008
Messages : 2 886
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 2 886
Points : 4 372
Points : 4 372
Je ne fais que lire l'aide :

Citation:
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...
__________________
Mes tutoriels Delphi
Andnotor est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/02/2013, 10h30   #8
Paul TOTH
Expert Confirmé Sénior
 
Avatar de Paul TOTH
 
Homme Paul TOTH
Freelance
Inscription : novembre 2002
Messages : 4 544
Détails du profil
Informations personnelles :
Nom : Homme Paul TOTH
Âge : 43
Localisation : Réunion

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

Informations forums :
Inscription : novembre 2002
Messages : 4 544
Points : 11 931
Points : 11 931
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%
Paul TOTH est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 01h16.


 
 
 
 
Partenaires

Hébergement Web