FileMapping für grosse Dateien
Verfasst: 22.05.2007 05:26
Hier mal ein paar Funktionen um grosse Dateien schnell zu lesen bzw. zu
überschreiben.
Einsatzgebiet sind Hexeditoren, Dateipatcher usw., für Dateien die normal
nicht in den Speicher passen
Geschwindigkeitszuwachs könnte ihr ja mal selber testen, über doppelt so
schnell wie die nativen PB-Funktionen sollte es immer sein
Die Funktionsnamen entsprechen denen von PB mit _M für mapped
angehängt.
Für jede Datei ist eine strukturierte Variable vom Typ FileMap anzulegen!
oder
Allgemeine Funktionen:
Funktionen zum Lesen:
Achtung: wenn der zu lesende Wert über das Dateiende hinausgeht,
ist das Ergebnis #False und der Dateizeiger befindet sich am Dateiende!
Ausnahme ist ReadData_M, hier wird bis zum Dateiende gelesen und die
Anzahl gelesener Bytes als Ergebnis zurückgegeben
Funktionen zum Schreiben:
Im Erfolgsfalle ist das Ergebnis #True
Sollte der zu schreibende Wert über das Dateiende hinausgehen, wird
garnichts geschrieben, es sei den das optionale Flag Append ist #True, der
Dateizeiger befindet sich hinterher immer am Dateiende!
Und hier der Code:
Nutzung auf eigene Gefahr, Verbesserungsvorschläge, Fehlermeldungen
usw. willkommen.
überschreiben.
Einsatzgebiet sind Hexeditoren, Dateipatcher usw., für Dateien die normal
nicht in den Speicher passen

Geschwindigkeitszuwachs könnte ihr ja mal selber testen, über doppelt so
schnell wie die nativen PB-Funktionen sollte es immer sein

Die Funktionsnamen entsprechen denen von PB mit _M für mapped
angehängt.
Für jede Datei ist eine strukturierte Variable vom Typ FileMap anzulegen!
Code: Alles auswählen
Define.FileMap File
Code: Alles auswählen
Global File.FileMap
Code: Alles auswählen
Result.l = CloseFile_M(*File.FileMap); schließt die gemappte Datei
Result.l = OpenFile_M(*File.FileMap, FileName.s, Append.l = #False); Öffnet Datei zum lesen und schreiben
Result.l = ReadFile_M(*File.FileMap, FileName.s); Öffnet Datei nur zum lesen
Result.l = Eof_M(*File.FileMap)
Result.q = Loc_M(*File.FileMap)
Result.q = Lof_M(*File.FileMap)
Result.l = FileSeek_M(*File.FileMap, pos.q)
Achtung: wenn der zu lesende Wert über das Dateiende hinausgeht,
ist das Ergebnis #False und der Dateizeiger befindet sich am Dateiende!
Ausnahme ist ReadData_M, hier wird bis zum Dateiende gelesen und die
Anzahl gelesener Bytes als Ergebnis zurückgegeben
Code: Alles auswählen
Result.b = ReadByte_M(*File.FileMap)
Result.c = ReadCharacter_M(*File.FileMap)
Result.q = ReadData_M(*File.FileMap, *Buffer, length.q); Ergebnis sind die tatsächlich gelesenen Bytes
Result.d = ReadDouble_M(*File.FileMap)
Result.f = ReadFloat_M(*File.FileMap)
Result.l = ReadLong_M(*File.FileMap)
Result.q = ReadQuad_M(*File.FileMap)
Result.w = ReadWord_M(*File.FileMap)
Im Erfolgsfalle ist das Ergebnis #True
Sollte der zu schreibende Wert über das Dateiende hinausgehen, wird
garnichts geschrieben, es sei den das optionale Flag Append ist #True, der
Dateizeiger befindet sich hinterher immer am Dateiende!
Code: Alles auswählen
Result.l = WriteByte_M(*File.FileMap, value.b)
Result.l = WriteCharacter_M(*File.FileMap, value.c)
Result.l = WriteData_M(*File.FileMap, *Buffer, length.q)
Result.l = WriteDouble_M(*File.FileMap, value.d)
Result.l = WriteFloat_M(*File.FileMap, value.f)
Result.l = WriteLong_M(*File.FileMap, value.l)
Result.l = WriteQuad_M(*File.FileMap, value.q)
Result.l = WriteWord_M(*File.FileMap, value.w)
Code: Alles auswählen
; German forum: http://www.purebasic.fr/german/viewtopic.php?p=152894#152894
; Author: ts-soft
; Date: 22. May 2007
; OS: Windows
; Demo: No
Structure FileMap
oFile.l
FileID.l
hView.l
pos.q
maxpos.q
write.b
append.b
EndStructure
Procedure CloseFile_M(*File.FileMap)
If *File\hView <> 0
If UnmapViewOfFile_(*File\hView)
CloseHandle_(*File\oFile)
CloseFile(*File\FileID)
ProcedureReturn #True
EndIf
EndIf
EndProcedure
Procedure OpenFile_M(*File.FileMap, FileName.s, Append.l = #False)
*File\maxpos = FileSize(FileName)
If *File\maxpos > 0
*File\FileID = OpenFile(#PB_Any, FileName)
If *File\FileID
*File\oFile = CreateFileMapping_(FileID(*File\FileID), 0, #PAGE_READWRITE, 0, 0, 0)
If *File\oFile
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_WRITE, 0, 0, 0)
If *File\hView
*File\pos = 0
*File\write = #True
If Append = #True
*File\append = #True
EndIf
ProcedureReturn #True
EndIf
EndIf
EndIf
EndIf
EndProcedure
Procedure CreateFile_M(*File.FileMap, FileName.s, Size.q, Append.l = #False)
Protected FileID.l = CreateFile(#PB_Any, FileName)
If FileID
FileSeek(FileID, Size)
SetEndOfFile_(FileID(FileID))
CloseFile(FileID)
ProcedureReturn OpenFile_M(*File, FileName, Append)
EndIf
EndProcedure
Procedure ReadFile_M(*File.FileMap, FileName.s)
*File\maxpos = FileSize(FileName)
If *File\maxpos > 0
*File\FileID = ReadFile(#PB_Any, FileName)
If *File\FileID
*File\oFile = CreateFileMapping_(FileID(*File\FileID), 0, #PAGE_READONLY, 0, 0, 0)
If *File\oFile
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
*File\pos = 0
*File\write = #False
ProcedureReturn #True
EndIf
EndIf
EndIf
EndIf
EndProcedure
Procedure Eof_M(*File.FileMap)
If *File\maxpos <= *File\pos
ProcedureReturn #True
EndIf
EndProcedure
Procedure.q Loc_M(*File.FileMap)
ProcedureReturn *File\pos
EndProcedure
Procedure.q Lof_M(*File.FileMap)
ProcedureReturn *File\maxpos
EndProcedure
Procedure FileSeek_M(*File.FileMap, pos.q)
If pos <= *File\maxpos And pos >= 0
*File\pos = pos
ProcedureReturn #True
EndIf
EndProcedure
Procedure.b ReadByte_M(*File.FileMap)
Protected *result.Byte = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Byte)
*File\pos + SizeOf(Byte)
ProcedureReturn *result\b
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure.c ReadCharacter_M(*File.FileMap)
Protected *result.Character = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Character)
*File\pos + SizeOf(Character)
ProcedureReturn *result\c
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure.q ReadData_M(*File.FileMap, *Buffer, length.q)
Protected *result = *File\hView + *File\pos
If *File\pos + length <= *File\maxpos
CopyMemory(*result, *Buffer, length)
*File\pos + length
ProcedureReturn length
Else
length = *File\maxpos - *File\pos
CopyMemory(*result, *Buffer, length)
*File\pos = *File\maxpos
ProcedureReturn length
EndIf
EndProcedure
Procedure.d ReadDouble_M(*File.FileMap)
Protected *result.Double = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Double)
*File\pos + SizeOf(Double)
ProcedureReturn *result\d
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure.f ReadFloat_M(*File.FileMap)
Protected *result.Float = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Float)
*File\pos + SizeOf(Float)
ProcedureReturn *result\f
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure.l ReadLong_M(*File.FileMap)
Protected *result.Long = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Long)
*File\pos + SizeOf(Long)
ProcedureReturn *result\l
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure.q ReadQuad_M(*File.FileMap)
Protected *result.Quad = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Quad)
*File\pos + SizeOf(Quad)
ProcedureReturn *result\q
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure.s ReadString_M(*File.FileMap)
Protected *result.Byte = *File\hView + *File\pos
Protected tmp.l = *result
Protected length.l, finish.l
Repeat
Select *result\b
Case 0
finish = #True
*File\pos + length
Case 13, 10
finish = #True
*File\pos + length + 1
*result + 1
If *result\b = 13 Or *result\b = 10
*File\pos + 1
EndIf
Default
length + 1
*result + 1
EndSelect
Until finish
ProcedureReturn PeekS(tmp, length, #PB_Ascii)
EndProcedure
Procedure.w ReadWord_M(*File.FileMap)
Protected *result.Word = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Word)
*File\pos + SizeOf(Word)
ProcedureReturn *result\w
Else
*File\pos = *File\maxpos
EndIf
EndProcedure
Procedure WriteByte_M(*File.FileMap, value.b)
If *File\write
Protected *result.Byte = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Byte)
*result\b = value
*File\pos + SizeOf(Byte)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteByte(*File\FileID, value)
*File\pos + SizeOf(Byte)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteCharacter_M(*File.FileMap, value.c)
If *File\write
Protected *result.Character = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Character)
*result\c = value
*File\pos + SizeOf(Character)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteCharacter(*File\FileID, value)
*File\pos + SizeOf(Character)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteData_M(*File.FileMap, *Buffer, length.q)
If *File\write
Protected *result = *File\hView + *File\pos
If *File\pos + length <= *File\maxpos
CopyMemory(*Buffer, *result, length)
*File\pos + length
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteData(*File\FileID, *Buffer, length)
*File\pos + length
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteDouble_M(*File.FileMap, value.d)
If *File\write
Protected *result.Double = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Double)
*result\d = value
*File\pos + SizeOf(Double)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteDouble(*File\FileID, value)
*File\pos + SizeOf(Double)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteFloat_M(*File.FileMap, value.f)
If *File\write
Protected *result.Float = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Float)
*result\f = value
*File\pos + SizeOf(Float)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteFloat(*File\FileID, value)
*File\pos + SizeOf(Float)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteLong_M(*File.FileMap, value.l)
If *File\write
Protected *result.Long = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Long)
*result\l = value
*File\pos + SizeOf(Long)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteLong(*File\FileID, value)
*File\pos + SizeOf(Long)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteQuad_M(*File.FileMap, value.q)
If *File\write
Protected *result.Quad = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Quad)
*result\q = value
*File\pos + SizeOf(quad)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteQuad(*File\FileID, value)
*File\pos + SizeOf(Quad)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
Procedure WriteString_M(*File.FileMap, value.s)
Protected value_a.s
CompilerIf #PB_Compiler_Unicode
value_a = Space(StringByteLength(value, #PB_Ascii))
PokeS(@value_a, value, #PB_Any, #PB_Ascii)
CompilerElse
value_a = value
CompilerEndIf
ProcedureReturn WriteData_M(*File, @value_a, Len(value))
EndProcedure
Procedure WriteStringN_M(*File.FileMap, value.s)
value + #CRLF$
Protected value_a.s
CompilerIf #PB_Compiler_Unicode
value_a = Space(StringByteLength(value, #PB_Ascii))
PokeS(@value_a, value, #PB_Any, #PB_Ascii)
CompilerElse
value_a = value
CompilerEndIf
ProcedureReturn WriteData_M(*File, @value_a, Len(value))
EndProcedure
Procedure WriteWord_M(*File.FileMap, value.w)
If *File\write
Protected *result.Word = *File\hView + *File\pos
If *File\maxpos >= *File\pos + SizeOf(Word)
*result\w = value
*File\pos + SizeOf(Word)
ProcedureReturn #True
ElseIf *File\append
If UnmapViewOfFile_(*File\hView)
FileSeek(*File\FileID, *File\pos)
WriteWord(*File\FileID, value)
*File\pos + SizeOf(Word)
*File\maxpos = *File\pos
*File\hView = MapViewOfFile_(*File\oFile, #FILE_MAP_READ, 0, 0, 0)
If *File\hView
ProcedureReturn #True
EndIf
EndIf
Else
*File\pos = *File\maxpos
EndIf
EndIf
EndProcedure
usw. willkommen.