Lecture d’un fichier ligne à ligne
Lire un fichier ligne à ligne prend du temps. Et pour Moebius, j’ai eu besoin d’améliorer cela.
Premier test : charger le fichier en mémoire, et lire directement les lignes à partir de la mémoire
Second test : charger le fichier dans une chaîne, et en extraire ligne après ligne via un StringField.
DeleteFile(GetTemporaryDirectory()+ "filetest.txt") If CreateFile(0, GetTemporaryDirectory()+ "filetest.txt") For Inc = 0 To 40000 ;WriteString(0, LSet("", Random(255), "a")+Chr(10)) ; Linux ;WriteString(0, LSet("", Random(255), "b")+Chr(13)) ; MacOS WriteString(0, LSet("", Random(255), "c")+Chr(13)+Chr(10)) ; Windows Next CloseFile(0) EndIf ProcedureDLL.s PeekLine(*BufMem = 0, BufLen = 0) Protected *ptrChar.Character, *ptrStr.Character, *ptrEof Protected lLength.l Protected cChar.c, cCharBis.c Static MemOffset, MemLen, *MemBuf Static bSystem.b If *BufMem And BufLen *MemBuf = *BufMem MemLen = BufLen MemOffset = 0 EndIf If *MemBuf And MemLen *ptrChar = *MemBuf + MemOffset *ptrEof = *MemBuf + MemLen *ptrStr = *ptrChar If MemOffset < MemLen While *ptrChar< *ptrEof cChar = *ptrChar\c *ptrChar = *ptrChar + SizeOf(Character) If cChar = 13 Break EndIf If cChar = 10 Break EndIf lLength + 1 Wend If *ptrChar < *ptrEof cCharBis = *ptrChar\c If cCharBis + cChar = 23 *ptrChar = *ptrChar + SizeOf(Character) EndIf EndIf MemOffset = *ptrChar - *MemBuf ProcedureReturn PeekS(*ptrStr, lLength) Else ProcedureReturn Chr(1) EndIf Else ProcedureReturn Chr(1) EndIf EndProcedure lNbLines = 0 TimeStart.l = ElapsedMilliseconds() Global Stream.l = ReadFile(#PB_Any, GetTemporaryDirectory()+ "filetest.txt") If Stream MemBufferLen = Lof(Stream) If MemBufferLen *MemBuffer = AllocateMemory(MemBufferLen) If *MemBuffer If ReadData(Stream, *MemBuffer, MemBufferLen) = MemBufferLen CloseFile(Stream) Line.s = PeekLine(*MemBuffer, MemBufferLen) Repeat lNbLines + 1 ; Debug Line Line = PeekLine() Until Line = Chr(1) FreeMemory(*MemBuffer) EndIf EndIf EndIf EndIf TimeEnd.l = ElapsedMilliseconds() Debug TimeStart Debug TimeEnd Debug "Time #1 > " + Str(TimeEnd - TimeStart)+"ms" Debug lNbLines lNbLines = 0 TimeStart.l = ElapsedMilliseconds() Global Stream.l = ReadFile(#PB_Any, GetTemporaryDirectory()+ "filetest.txt") If Stream MemBufferLen = Lof(Stream) If MemBufferLen *MemBuffer = AllocateMemory(MemBufferLen) If *MemBuffer If ReadData(Stream, *MemBuffer, MemBufferLen) = MemBufferLen FileContent.s = PeekS(*MemBuffer, MemBufferLen) EndIf CloseFile(Stream) FreeMemory(*MemBuffer) EndIf EndIf For Inc = 0 To CountString(FileContent, Chr(13)) - 1 Line = StringField(FileContent, Inc +1, Chr(13)) Line = RemoveString(Line, Chr(13)) Line = RemoveString(Line, Chr(10)) lNbLines + 1 ; Debug Line Next EndIf TimeEnd.l = ElapsedMilliseconds() Debug TimeStart Debug TimeEnd Debug "Time #2 > " + Str(TimeEnd - TimeStart)+"ms" Debug lNbLines
Ce code permet de gagner un peu plus de temps que de lire ligne à ligne un fichier via StringField. Un gain de 181%.
Time #1 > 2324ms Time #2 > 421306ms
Un grand merci à Gnozal pour le code initial.
[EDIT du 29/03/09] Amélioré pour pouvoir traiter les fins de ligne Windows, MacOs et Linux, sur n’importe quel système
Ajouter un commentaire