Page 1 sur 2
[..] Supression de caractere dans gros fichier
Posté : ven. 04 nov. 2011 22:28
par Iste
Salutations,
Je viens demander a l'aide car je manque cruellement de temps en ce moment et n'ai pas le temps de me pencher sur un probleme.
J'ai un 'petit' fichier base de données qui a été corrompu suite a un passage sous linux (me demandez pas pourquoi...)
En gros, c'est un fichier texte et il a été ajouté en fin de chaque ligne (crlf) un cr...
La base de données a continué d'etre rempli, donc pas question de se la jouer "une ligne sur deux", je cherche donc a supprimer tout les cr seul !
Bien sur, c'est facile a faire, alors pourquoi cette demande ? car les fichiers sont tres gros et je ne sais pas comment lire et modifier un fichier partiellement en AutoIt. Du coup, je me retrouve avec deux variable de plusieurs go, ce qui passe bien sur pas. Surement une histoire de FileReadLine() mais chez moi la memoire se sature a tout les coup.
Je sais bien le faire en Java, mais la machine ou se trouve se fichier est pas facile d’accès, je prend donc moins de risque en lançant un .exe
Dans l'absolu rien de vital, je récupérerai ces fichier plus tard sur mon ordi pour les modifier. Mais ca sera long, surtout a reenvoyer... tres long... et difficile de se passer de cette base de données pour le moment :s
merci d'avance pour vos réponses.
Re: [..] Supression de caractere dans gros fichier
Posté : ven. 04 nov. 2011 22:38
par jchd
GnuGrep ?
Re: [..] Supression de caractere dans gros fichier
Posté : ven. 04 nov. 2011 23:19
par moi
_ReplaceStringInFile()
permet de remplacer certains caractère dans un fichier y compris remplacer les "cr" en ""
c'est ce que tu cherche

Re: [..] Supression de caractere dans gros fichier
Posté : ven. 04 nov. 2011 23:27
par Tlem
En AutoIt, je verrais deux solutions :
1 - On ouvre le fichier source en lecture, on le lit caractère par caractère tout en le 'reconstruisant' au fur et à mesure dans un fichier neuf sans les CR évidement.
2 - On utilise FileSetPos pour se déplacer dans le fichier, y lire les valeurs une à une puis si on trouve un CR on l'efface (cf la section Remarks de la commande FileSetPos), puis on continue ...
J'ai pas testé, mais je pense que ça fonctionne.
Edit : @moi
_ReplaceStringInFile() sera limité par la taille du fichier.
J'ai déjà évoqué cela dans un de mes précédents message. La limite ce situe aux environs de 120 Mo ...
Re: [..] Supression de caractere dans gros fichier
Posté : ven. 04 nov. 2011 23:31
par moi
ou alors fileread puis stringreplace.
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 00:14
par Iste
@moi : avez vous lu ou juste réfléchi a la problématique soulevée ?
@Tlem : j'ai un peu de temps, je vais regarder ca de suite voir ce que ca donne.
@jchd : ca serait pas un vilain troll ca ?
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 00:19
par Tlem
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 00:30
par Iste
Je viens de faire le test son mon pc de boulot, meme probleme de saturation de mémoire :/
Enfin, ca reste bien moindre et fix. Mais je pense pas pour autant que ca passera :s
Je vias essayer de regarder ce code demain matin (la un peu mort)
merci beaucoup !
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 12:18
par mikell
Heu mes excuses par avance pour le côté un peu bourrin de la méthode, mais pourquoi ne pas utiliser un "file splitter" comme HJSplit ou
http://www.addictivetips.com/windows-ti ... ext-files/ pour découper le fichier en morceaux raisonnables, traiter chaque morceau, puis réassembler ?

Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 12:29
par Tlem
Je suppose que le but est de faire ca en AutoIt pour un contrôle total.
En fait, AutoIt peut faire la même chose ...
Il suffit de lire le fichier par tronçon puis de traiter en mémoire et enfin d'enregistrer.

Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 13:39
par Iste
@mikell : Ca pourrait etre une solution, mais exécuter un script AutoIt est déja limite, vais pas me risquer a installer un autre logiciel.
Le plus, il reste le risque de couper le fichier sur un des éléments corrompu et de ne pas le voir, ou de couper au milieu d'un crlf et de prendre le cr pour un probleme.
Apres oui AutoIt pourrait le faire, mais le travail sur des fichier prend un peu trop de mémoire, donc au final je serai quand même coincé ^^'
Bref, je vais essayer de trouver un peu de temps cet aprem pour regarder le script que m'a linké Tlem pour comprendre ce qui demande de la mémoire dedans. Je vous tiendrais au courant.
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 14:47
par mikell
Tlem a écrit :Je suppose que le but est de faire ca en AutoIt pour un contrôle total.

Ah, j'avais cru comprendre que le but était d'abord de faire ça de manière fiable et sécurisée
@Iste
"HJSplit for MS-DOS" fait 10 Ko, peut être mis en FileInstall et fonctionne en ligne de commande
De plus les coupures sont franches, sans ajout ou retrait de quoi que ce soit
Enfin "couper le fichier sur un des éléments corrompu" j'y crois pas trop vu que la corruption c'est juste l'ajout de CR
Je vois plutôt ces arguments comme : " zallez voir, ake je vais y arriver à faire ça en AutoIt pur et dur, nondidiou "

Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 14:56
par moi
Iste a écrit : il a été ajouté en fin de chaque ligne (crlf) un cr...
on peut utiliser un _FileReadToArray et remplacer tout les "cr" par des ""
mais le probleme est la taille de l'array qui risque d'être plus qu'énorme...
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 15:41
par Iste
@mikell : Bah si je coupe a coté d'un cr, comment savoir qu'il est seul ?
Je peux regarder l'autre fichier, mais ca devient un peu compliqué pour pas grand chose. De plus, il me faudrait quand meme découper des centaines de petits bout, ca risque de devenir glissant.
Enfin, j'aimerai quand meme avoir un code tout pret, pour le jour ou le probleme reviendra...
Je garde quand meme cette solution de coté car si ce logiciel ne consomme pas trop pendant la découpe (contrairement a ce que je sais faire avec AutoIt pour le moment) ca pourrait bien dépanner.
@moi : bien ! Vous venez de comprendre le probleme.
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 16:08
par Iste
Alors, avec ce code ca semble passer (bien que je suis sur d'avoir essayé :/)
Code : Tout sélectionner
$file = FileOpenDialog("","D:\Dev\Tests\Thunderbird\Thunderbird\Data\profile\Mail\Local Folders\Inbox.sbd\Iste.sbd\iste.me.sbd","")
Local $hInpf = FileOpen($file)
If $hInpf <> -1 Then
Local $hOutf = FileOpen($file & ".out", 2)
If $hOutf <> -1 Then
Local $ret, $data, $done
Do
;~ $ret = FileSetPos($hInpf, 58, $FILE_CURRENT)
;~ If Not $ret Then ExitLoop
$data = FileRead($hInpf, 2112)
$done = (@error = -1) ; read incomplete (EOF reached) but maybe something to write anyway
FileWrite($hOutf, StringReplace($data, @CR&@CR, @CR))
; process write error
until $done
FileClose($hInpf)
FileClose($hOutf)
Else
; process error
EndIf
; process error
EndIf
Mais je retrouve le meme probleme de découpe (des @CR@CR qui restent) De plus, a quoi sert le FileSetPos() du coup ? je ne comprend pas trop l'utilité, si ce n'est sauter 58 caractères sur 2112 :/ (ainsi que les 58premiers)
Si ca marche bien, j'ajouterai de quoi eviter les découpe entre deux cr
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 16:55
par jchd
@iste,
Pourquoi un troll ? J'pige pas, mais alors pas du tout.
Ceci dit, si tu tiens absolument à faire ça en AutoIt, tu as capté que ça va prendre des siècles (toute proportion gardée).
Approche con : tu traites caractère par caractère avec un look-ahead d'un caractère (prévoir deux fois des siècles).
Approche plus chiante et moins efficace en AutoIt : tu lis un buffer (chais pas moi, 1 Mo ou ce que tu veux), tu fais ton regexpreplace, tu testes le caractère suivant dans le fichier si le dernier caractère du buffer est CR pour savoir comment le traiter, tu récris tout, etc.
AutoIt ne disposant pas de pointeurs ne facilite pas vraiment ce genre de traitements sur des chaînes longues. PCRE est efficace mais les deux interfaces dispo sous AutoIt forcent la "recompilation" du pattern à chaque emploi.
@Tlem,
Euh, ce mix (qu'entends-tu par là ?) traite un format fixe, alors qu'on a ici un format variable si j'ai bien compris.
Si tu voulais dire que j'avais initialement mal interprété le coup du "jump", certes c'est vrai but English is not my mothertongue.
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 17:09
par GaRydelaMer
Salut
j'ai eu le même soucis avec Thunderbird, quand j'ai voulu partager ma boite sous windows et linux.
Bref, un script de ce genre marche pas ?:
Le FileReadline lis chaque ligne avec comme carractère de ligne: ( CHR(10) ou @LF )
FileWriteLine ajoute automatiquement @CRLF comme séparateur de ligne si il y a pas de @CR ou @LF à la fin
C'est pour ca que je traite la ligne avec StringStripCR et StringStripWS
Code : Tout sélectionner
$fileIn = FileOpen("test.txt", 0)
$fileOut = FileOpen("test.txt.out", 2)
; Check if file opened for reading OK
If $fileIn = -1 Then
MsgBox(0, "Error", "Unable to open file.")
Exit
EndIf
; Read in lines of text until the EOF is reached
While 1
$line = FileReadLine($fileIn)
If @error = -1 Then ExitLoop
$line = StringStripCR($line)
$line = StringStripWS($line, 3) ; Début et fin
If $line = "" Then Continueloop
FileWriteLine($fileOut, $line)
Wend
FileClose($fileIn)
FileClose($fileOut)
Edit:
J'ai ajouter le saut en cas de ligne vierge: If $line = "" Then Continueloop à toi de voir si il faut le laisser
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 17:18
par jchd
L'éjection de _toutes_ les lignes vides n'est pas forcément correct !
En faisant ainsi, on ne sait pas si on est dans le cas "terminaison CRLF suivi de CR puis autre chose" ou "CRLF suivi de CRLF puis autre chose".
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 17:52
par mikell
Heu autre chose, est-ce que traiter les lignes par "paquets" ne marcherait pas ?
Code : Tout sélectionner
$fileOut = FileOpen("test.txt.out", 1)
$n = 1
While 1
$fileIn = FileOpen("test.txt", 0)
For $i = $n to $n + 99
$line = FileReadLine($fileIn, $i)
If @error = -1 Then ExitLoop 2
If StringInStr(StringRight($line, 3), @CR) Then StringReplace($line, @CR, "")
If $line = "" Then Continueloop
FileWriteLine($fileOut, $line)
Next
$n += 100
FileClose($fileIn)
Wend
FileClose($fileIn)
FileClose($fileOut)
Re: [..] Supression de caractere dans gros fichier
Posté : sam. 05 nov. 2011 17:52
par Iste
@jchd : Bah c'est une question que je me pose quand on me donne en réponse le nom d'une commande linux alors que je suis manifestement dans un environnement windows.
Apres, si il y a une implementation que je ne connais pas, tant mieux, mais il faudra quand meme que je passe par AutoIt pour d'autre raison (recherche des fichiers, log, test)
Sinon, comme la solution de "FileRead($hInpf, 2112)" ne consome pas beaucoup de mémoire, j'avais bien l'intention de noter si la chaine fini par un cr pour savoir que faire pour la prochaine.
Me faut juste le temps de m'y mettre, mais j'aurai vraiment bien aimé comprendre l'utilité des FileSetPos() dans le code que Tlem m'a retrouvé.
@GaRydelaMer : j'y ai pensé, mais je ne savais pas comment se comporterai FileReadLine() face a un @cr@cr@lf (une ligne ? deux ?) et si il me rapportait la fin de ligne..
J'aurai pu tester, mais comme dit, manque de temps ^^'
je viens de tester votre code donc, il fonction bien, a cela pret qu'il est extrêmement lent :s (surement du a l’écriture de chaque ligne séparément)
mais comme dit par jchd, je perd les ligne vide (pas moyen de savoir si la ligne contenais juste @cr ou @cr@lf)
Au passage, je me suis trompé au début, c'est bien des @cr@cr@lf que je cherche a changer en @cr@lf
edit :
@mikell je ne comprend pas bien ce que cela apporte, mais de toute facon, il me semble que l'utilisation de filereadligne pose probleme.
Sinon, voici un prototype de la fonction que je vais surement utiliser :
► Afficher le texte
Code : Tout sélectionner
Func correct(Const $file)
Local $hInpf = FileOpen($file)
If $hInpf <> -1 Then
Local $hOutf = FileOpen($file & ".out", 2)
If $hOutf <> -1 Then
Local $ret, $data, $done
Local $cr = False
Do
$data = FileRead($hInpf, 2112)
$done = (@error = -1)
If StringLeft($data, 1) = @CR And $cr Then $data = StringTrimLeft($data, 1)
FileWrite($hOutf, StringReplace($data, @CR & @CR, @CR))
If StringRight($data, 1) = @CR Then
$cr = True
Else
$cr = False
EndIf
Until $done
FileClose($hOutf)
EndIf
EndIf
FileClose($hInpf)
FileDelete($file)
FileMove($file & ".out", $file)
EndFunc ;==>correct
si vous voyez des erreurs...