RootsLabs

More than a tool ! GitHub Google+ LinkedIn RSS

Lecture d’un fichier ligne à ligne

Progi1984 - Commentaires (0)

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

Commentaire :