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
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
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()