Page 1 sur 1

ReplaceString

Publié : ven. 21/mai/2004 13:01
par LOULOU25
La fonction ReplaceString bugge avec le mesage suivant sur les variables déclarés de plus de 64 K° :
Stack Overflow. Can occur during errant recursion or when a function creates a particular large array on the stack

Quelq'un connait-il la solution à ce problême ou une solution analogue ?

Code : Tout sélectionner

 Procedure ManipulationBufferSize(Bytes) 
  PBStringBase.l = 0 
  PBMemoryBase.l = 0 
  !MOV Eax, dword [PB_StringBase] 
  !MOV [Esp+4],Eax 
  !MOV Eax, dword [PB_MemoryBase] 
  !MOV [Esp+8],Eax 
  HeapReAlloc_(PBMemoryBase, #GMEM_ZEROINIT, PBStringBase, Bytes) 
  !MOV dword [_PB_StringBase],Eax 
EndProcedure 
OnErrorGoto(?fin)


ManipulationBufferSize(1084576) 

calldebugger
toto.s= "BONJOUR"+space(500000)+"XY"

toto= ReplaceString(toto,"BO","AC",1,1)


Debug Left(toto,8)

Fin:
Debug GetErrorDescription() 

Publié : ven. 21/mai/2004 13:37
par Heis Spiter
Essaie avec la Lib LargeString de cederavic http://www.serveurperso.com/~cederavic/mecrea.htm

Publié : ven. 21/mai/2004 13:40
par fweil
LOULOU25,

Bien qu'il ne soit pas interdit de modifier l'allocation dynamique pour la déclaration de chaines de + de 64K, les fonctions proposées par PureBasic sont quant à elles réalisées et spécifiées avec cette limite de 64K. Ce qui fait qu'il n'est pas possible de les utiliser avec une allocation non standard.

Par contre rien n'interdit de ré-écrire quelques fonctions comme Mid, Left, Right, Ucase, Lcase, FindString et ReplaceString ...

Je vais m'y pencher de mon côté pour me faire une petite récré, mais si qq'un d'autre veut également y travailler, on peut se partager le boulot ...

Le principe est simple à mon avis, consistant à faire de l'analyse de tableau d'octets une fois déclarée la chaine longue.

Slts

Publié : ven. 21/mai/2004 13:58
par LOULOU25
Heis Spiter a écrit :Essaie avec la Lib LargeString de cederavic http://www.serveurperso.com/~cederavic/mecrea.htm
Cette bibliothéque ne fonctionne pas sur les chaines de + de 64 K°, je l'ais déjà essayé.

Publié : ven. 21/mai/2004 14:04
par LOULOU25
LOULOU25 a écrit :,Fveill

Voici un bout de code qui fonctionne sur un remplacement global dans une chaine mais qui est extrémement lent. N'ayant pas les compétences requises pour aller plus loin dans le code peut-être celà t'aidera-til a gagner du temps et à sortir une possibilité plus rapide en temps d'execution

Code : Tout sélectionner

  Procedure.l ReplaceFileData(FileName.s,  *searchdata.l, searchdataLen.l, *replacedata, replacedataLen.l) 
    Protected templ.l 
    Protected *tempmem.l 
    Protected fileLen.l 
    Protected numResults.l 
    Protected searchdataLen.l
    Protected replacedataLen.l
    Protected j
    Protected i 
    
    
    fileLen = FileSize(FileName)  
    If fileLen < 1 Or searchdataLen < 1 
      ProcedureReturn -1 
    EndIf 
    
    If OpenFile(0, FileName) 
      *tempmem = AllocateMemory(fileLen) 
      ReadData(*tempmem, fileLen) 
      CloseFile(0) 
     
      If CreateFile(0, FileName) 
        i = 0 
        While i <= fileLen - 1 
          If PeekB(*tempmem + i) <> PeekB(*searchdata) 
            WriteByte(PeekB(*tempmem + i)) 
            i + 1 
          Else 
            same = #True : j=1 
            While same = #True And j < searchdataLen 
              If PeekB(*tempmem + i + j) <> PeekB(*searchdata + j) 
                same = #False 
              Else 
                j+1 
              EndIf 
            Wend 
            If same = #True 
              WriteData(*replacedata, replacedataLen) 
              numResults + 1 
            Else 
            WriteData(*tempmem + i, j) 
            EndIf 
            i + j 
          EndIf 
        Wend 
       CloseFile(0) 
       FreeMemory(*tempmem)
    Else 
      ProcedureReturn -3 
      EndIf 
      
    Else 
      ProcedureReturn -2 
    EndIf 
    
    ProcedureReturn numResults 
  EndProcedure

;Invocation de la procédure 
 searchstring.s="#=" + Trim(code_societe)  ; This is the text to look for
      replacestring.s="#=" + Trim(Nom_societe) ; Replace every found occurence of the above string with this string
      Length=Len(searchstring) 
      Lenght1 = Len(replacestring)   
      ReplaceFileData(strChemin,@searchstring,Length,@replacestring,Lenght1)




[/code]

Publié : ven. 21/mai/2004 15:11
par nico
j'ai écrit une procédure permettant de remplacer une chaine par une autre quelque soit la taille du fichier.

Cette procédure permet aussi de faire plusieurs remplacement de chaines en une seule passe.

Voir site Code FR - > Fichiers et Dossiers -> Lecture / écriture de fichier -> Remplacer une chaine


http://perso.wanadoo.fr/lesoldatinconnu/CodesFR

:)

Publié : ven. 21/mai/2004 15:53
par LOULOU25
nico a écrit :j'ai écrit une procédure permettant de remplacer une chaine par une autre quelque soit la taille du fichier.
Merci Nico ta procédure marche à merveille et rapidement

Publié : ven. 21/mai/2004 20:56
par fweil
Bon pour la forme, je poste la suite sur Trucs et Astuces

Publié : dim. 23/mai/2004 23:25
par ZapMan

Code : Tout sélectionner

;************************************************************
;* Le truc de Fred pour augmenter la taille du buffer texte *
;*   et éviter les plantage quand on manipule des grandes   *
;*    chaines de caractères.                                *
;************************************************************

Procedure SetStringManipulationBufferSize(Bytes)
  PBStringBase.l = 0
  PBMemoryBase.l = 0
  !MOV eax, dword [PB_StringBase]
  !MOV [esp+4],eax
  !MOV eax, dword [PB_MemoryBase]
  !MOV [esp+8],eax
  HeapReAlloc_(PBMemoryBase, #GMEM_ZEROINIT, PBStringBase, Bytes)
  !MOV dword [_PB_StringBase],eax
EndProcedure

; Set the buffer size for all strings to 1 MB.

SetStringManipulationBufferSize(1000000)
Avec ça, j'utilise toutes les fonctions de PB sur des textes de plus de 64ko (et je fais ça tous les jours !!)

Publié : lun. 24/mai/2004 8:52
par fweil
ZapMan,

Heuu : un affreux doute ? J'aurai pu avoir cet affreux doute + tôt !

Autant que je m'en souvienne le changement d'allocation dynamique il y a quelques mois n'avait pas d'effet sur les fonctions comme FindString etc ... mais maintenant si !

Donc tu as raison et merci, cela m'évitera de me prendre la tête plus sur ce point.

FindString et le reste fonctionne apparement sur des chaines longues si on utilise la procédure de changement de taille max et que l'on ne remet la valeur par défaut tout de suite derrière.

Dans le cas de traitement d'un fichier chargé d'un seul bloc dans un buffer, il suffit de faire par exemple un FindString(Peeks(*Buffer), Cherche, 1)) et c'est tout bon.

Et les performances suivent en conséquence.

Donc je laisse mes réflexions ci-dessus pour le temple de la honte et je travaille désormais avec cette idée en tête. Tout va bien en changeant simplement la taille max.

Slts

ReplaceString

Publié : lun. 24/mai/2004 14:05
par LOULOU25
Fveil,
Voici un bout de code qui te démontre le problême constaté sur les chaines de plus de 64 K° sachant effectivement que le problême ne se produit pas avec la fonction FINDSTRING mais seulement avec REPLACESTRING qui génére un "stack overflow" .
Logiquement tu devrais avoir un message d'erreur.

Code : Tout sélectionner

OnErrorGoto(?erreur)

  Procedure SetStringManipulationBufferSize(Bytes) 
  PBStringBase.l = 0 
  PBMemoryBase.l = 0 
  !MOV eax, dword [PB_StringBase] 
  !MOV [esp+4],eax 
  !MOV eax, dword [PB_MemoryBase] 
  !MOV [esp+8],eax 
  HeapReAlloc_(PBMemoryBase, #GMEM_ZEROINIT, PBStringBase, Bytes) 
  !MOV dword [_PB_StringBase],eax 
EndProcedure 
  
SetStringManipulationBufferSize(100012) 
CallDebugger

Toto.s = "BONJOUR" + Space(100000)+"ABCD"
Toto = ReplaceString(Toto,"ABCD","CDEFG",1,1)
Debug Right(toto,4)

Erreur:
Debug GetErrorDescription() 
Pour Zapman merci de m'envoyer le cas échéant un bout de programme qui fonctionne avec replacestring. Il s'agit peut-être d'une erreur de programmation de ma part.

Publié : lun. 24/mai/2004 23:43
par ZapMan
Mea Maxima Culpa

Il est vrai que je n'utilise pas TOUTES les fonctions texte de PB. En parcourant mes codes, je mes suis apperçu qu'en fait, je n'utilise jamais ReplaceString, ce qui explique que je n'avais pas constaté le bug de cette fonction. Je te promets par contre que je n'ai vraiment aucun souci avec left, right, len et findstring. Voici un code qui marche :

Code : Tout sélectionner

OnErrorGoto(?erreur) 

Procedure SetStringManipulationBufferSize(Bytes) 
  PBStringBase.l = 0 
  PBMemoryBase.l = 0 
  !MOV eax, dword [PB_StringBase] 
  !MOV [esp+4],eax 
  !MOV eax, dword [PB_MemoryBase] 
  !MOV [esp+8],eax 
  HeapReAlloc_(PBMemoryBase, #GMEM_ZEROINIT, PBStringBase, Bytes) 
  !MOV dword [_PB_StringBase],eax 
EndProcedure 
  
SetStringManipulationBufferSize(100012) 

Toto.s = "BONJOUR" + Space(100000)+"ABCD" 

;fs = ReplaceString(Toto,"ABCD","CDEFG",1,1)

        fs = FindString(Toto,"ABCD",1) 
        If fs
          Repeat 
            Toto=Left(Toto,fs-1)+"CDEFG"+Right(Toto,Len(Toto)-fs-Len("ABCD"))
            fs = FindString(Toto,"ABCD",1) 
          Until fs = 0
        EndIf 
 
Debug Right(toto,4) 

Erreur: 
Debug GetErrorDescription()