Units | | | | | Die erste Version meiner FileClass-Unit ist fertig
Bitte nicht mit der File-Unit verwechseln
Bisher ist die Auswahl an Klassen für XProfan ja noch ein bißchen dürftig, daher (und natürlich aus persönlichen Interesse) hab ich mich entschlossen eine FileClass zu erstellen. Diese Klasse kann fast beliebig viele Dateien gleichzeitig erstellen, bearbeiten oder lesen (unabhängig von den Profan-internen Befehlen). Alle Methoden (Funktionen in der Klasse) beruhen auf reinem Windows-API. Eine direkte Unterscheidung von Binär- und Textdateien gibt es nicht. Die Syntax ist auch sehr einfach. Im beiligendem Source sind alle Methoden ausführlich beschrieben, desweiteren habe ich 3 Beispiele beigefügt, die einen Einstieg erleichtern sollten. Die Unit soll, ich hoffe ja auch auf ein bißchen Teamwork, noch weiter ausgebaut werden. Einschränkungen zur Zeit: Fehlerbehandlung noch Stiefmütterlich Geschwindigkeit bei Zeilenweise einlesen von Texten noch nicht so besonders (bisher ist noch keine Pufferung eingebaut).
Dateisystemfunktionen, also erstellen von Ordnern, ermitteln von Pfaden usw. sind nicht geplant. Die Klasse soll lediglich Dateioperationen ausführen. Selbstverständlich kann man später auch separat eine FileSystemClass erstellen, die bei Bedarf von dieser Klasse erbt
Gruß Thomas (ts-soft)
$L
$H windows.ph
{
Class ?_File = -hFile&,
-FileError&,
+Error@,
+Close@,
+Create@,
+Eof@,
+Seek@,
+Loc@,
+Lof@,
+Open@,
+Read@,
+GetFile@,
+GetByte@,
+GetWord@,
+GetLong@,
+GetFloat@,
+GetString@,
+GetData@,
+PutByte@,
+PutWord@,
+PutLong@,
+PutFloat@,
+PutString@,
+PutStringCR@,
+PutData@,
+Version@
}
################################################
# Erstellen, öffnen und schliessen von Dateien #
################################################
Syntax: OBJEKT#.Create(FileName$)
Ergebnis: Handle des Files,
im Fehlerfall -1, OBJEKT#.Error wird auf TRUE gesetzt
Erklärung: Öffnet eine leere Datei. Existiert die angegebene Datei bereits,
wird diese geöffnet und durch eine leere ersetzt!!!
Proc ?_File.Create
Parameters FileName$
.FileError& = 0
{
.hFile& = ~CreateFile(Addr(FileName$),
OR(~GENERIC_WRITE,~GENERIC_READ),
0,
0,
~CREATE_ALWAYS,
~FILE_ATTRIBUTE_NORMAL,
0)
}
Case .hFile& = ~INVALID_HANDLE_VALUE : .FileError& = 1
Return .hFile&
EndProc
Syntax: OBJEKT#.Open(FileName$)
Ergebnis: Handle des Files,
im Fehlerfall -1, OBJEKT#.Error wird auf TRUE gesetzt
Erklärung: Öffnet die angegebene Datei oder erstellt eine,
falls noch keine existiert. Du kannst nun Lese- und Schreibfunktionen in dieser Datei ausführen
Proc ?_File.Open
Parameters FileName$
.FileError& = 0
{
.hFile& = ~CreateFile(Addr(FileName$),
OR(~GENERIC_WRITE, ~GENERIC_READ),
~FILE_SHARE_READ | ~FILE_SHARE_WRITE,
0,
~OPEN_ALWAYS,
~FILE_ATTRIBUTE_NORMAL,
0)
}
Case .hFile& = ~INVALID_HANDLE_VALUE : .FileError& = 1
Return .hFile&
EndProc
Syntax: OBJEKT#.Read(FileName$)
Ergebnis: Handle des Files,
im Fehlerfall -1, OBJEKT#.Error wird auf TRUE gesetzt
Erklärung: Öffnet eine existierende Datei FileName$ ausschließlich für Lese-Operationen
Proc ?_File.Read
Parameters FileName$
.FileError& = 0
{
.hFile& = ~CreateFile(Addr(FileName$),
~GENERIC_READ,
~FILE_SHARE_READ,
0,
~OPEN_EXISTING,
~FILE_ATTRIBUTE_NORMAL,
0)
}
Case .hFile& = ~INVALID_HANDLE_VALUE : .FileError& = 1
Return .hFile&
EndProc
Syntax: OBJEKT#.Close([File&])
Ergebnis: keins
Erklärung: Schließt die aktuelle Datei, welche damit nicht weiter benutzt werden kann
Wenn der optionale Parameter File& übergeben wird, wird diese Datei geschlossen, die
aktuelle Datei bleibt hiervon unbeeinflusst
Proc ?_File.Close
If %PCount = 1
Parameters file&
~CloseHandle(file&)
Else
~CloseHandle(.hFile&)
.hFile& = 0
EndIf
EndProc
###############
# Daten lesen #
###############
Syntax: OBJEKT#.GetByte()
Ergebnis: gelesenes Byte
Erklärung: Liest ein Byte aus der aktuell geöffneten Datei ein
Proc ?_File.GetByte
Declare temp1&, temp2#
Dim temp2#, 1
~ReadFile(.hFile&, Addr(temp1&), 1, Addr(temp2#), 0)
Dispose temp2#
Return temp1&
EndProc
Syntax: OBJEKT#.GetWord()
Ergebnis: gelesenes Word
Erklärung: Liest ein Word aus der aktuell geöffneten Datei ein
Proc ?_File.GetWord
Declare temp1&, temp2#
Dim temp2#, 2
~ReadFile(.hFile&, Addr(temp1&), 2, Addr(temp2#), 0)
Dispose temp2#
Return temp1&
EndProc
Syntax: OBJEKT#.GetLong()
Ergebnis: gelesenes Long&
Erklärung: Liest ein Long aus der aktuell geöffneten Datei ein
Proc ?_File.GetLong
Declare temp1&, temp2&
~ReadFile(.hFile&, Addr(temp1&), 4, Addr(temp2&), 0)
Return temp1&
EndProc
Syntax: OBJEKT#.GetFloat()
Ergebnis: gelesenes Float!
Erklärung: Liest ein Float aus der aktuell geöffneten Datei ein
Proc ?_File.GetFloat
Declare temp1!, temp2#
Dim temp2#, 8
~ReadFile(.hFile&, Addr(temp1!), 8, Addr(temp2#), 0)
Dispose temp2#
Return temp1!
EndProc
Syntax: OBJEKT#.GetString()
Ergebnis: gelesene TextZeile als Text$
Erklärung: Liest einen String aus der aktuell geöffneten Datei,
bis ein End Of Line Zeichen gefunden wird. UNIX oder DOS
Proc ?_File.GetString
Declare buffer#, bytesread&, Text$
Dim buffer#, 1
While ~SetFilePointer(.hfile&, 0, 0, ~FILE_CURRENT) < ~GetFileSize(.hfile&, 0)
~ReadFile(.hfile&, Addr(buffer#), 1, Addr(bytesread&), 0)
Case Byte(buffer#,0) = 0 : break
Case Byte(buffer#,0) = 10 : break
Text$ = Text$ + Chr$(Byte(buffer#,0))
EndWhile
Dispose buffer#
Return Translate$(Text$, Chr$(13), "")
EndProc
Syntax: OBJEKT#.GetData(MemoryBuffer&, LengthToRead&)
Ergebnis: keins (gelesene Bytes befinden sich im MemoryBuffer&)
Beschreibung: Liest den Inhalt der aktuellen Datei mit der
angegebenen Länge LengthToRead& (Anzahl zu einzulesender Zeichen)
in den angegebenen Speicherbereich MemoryBuffer& z.B. Adresse
einer Bereichsvariable
Proc ?_File.GetData
Parameters MemoryBuffer&, LengthToRead&
Declare buffer#
Dim buffer#, LengthToRead&
~ReadFile(.hFile&, MemoryBuffer&, LengthToRead&, Addr(buffer#), 0)
Dispose buffer#
EndProc
###################
# Daten schreiben #
###################
Die hier folgenden Methoden funktionieren nur,
wenn die Datei mit Schreib-Unterstützung geöffnet wurde
(entweder mit Create oder Open)
Syntax: OBJEKT#.PutByte(Wert&)
Ergebnis: keins
Erklärung: Schreibt einen Byte-Wert in die aktuelle Datei.
Proc ?_File.PutByte
Parameters Number&
Declare Temp#
Dim Temp#, 1
~WriteFile(.hFile&, Addr(Number&), 1, Temp#, 0)
Dispose Temp#
EndProc
Syntax: OBJEKT#.PutWord(Wert&)
Ergebnis: keins
Erklärung: Schreibt einen Word-Wert in die aktuelle Datei.
Proc ?_File.PutWord
Parameters Number&
Declare Temp#
Dim Temp#, 2
~WriteFile(.hFile&, Addr(Number&), 2, Temp#, 0)
Dispose Temp#
EndProc
Syntax: OBJEKT#.PutLong(Wert&)
Ergebnis: keins
Erklärung: Schreibt einen Long-Wert in die aktuelle Datei.
Proc ?_File.PutLong
Parameters Number&
Declare Temp&
~WriteFile(.hFile&, Addr(Number&), 4, Addr(Temp&), 0)
EndProc
Syntax: OBJEKT#.PutFloat(Wert!)
Ergebnis: keins
Erklärung: Schreibt einen Float-Wert in die aktuelle Datei.
Proc ?_File.PutFloat
Parameters Number!
Declare Temp!
~WriteFile(.hFile&, Addr(Number!), 8, Addr(Temp!), 0)
EndProc
Syntax: OBJEKT#.PutString(Text$)
Ergebnis: keins
Erklärung: Schreibt einen String in die aktuelle Datei
Proc ?_File.PutString
Parameters Text$
Declare Temp#
Dim Temp#, Len(Text$)
~WriteFile(.hFile&, Addr(Text$), Len(Text$), Addr(Temp#), 0)
Dispose Temp#
EndProc
Syntax: OBJEKT#.PutStringCR(Text$)
Ergebnis: keins
Erklärung: Schreibt einen String in die aktuelle Datei
und fügt ein EOL Zeilenumbruch hinzu
Proc ?_File.PutStringCR
Parameters Text$
Declare Temp#
Text$ = Text$ + Chr$(13) + Chr$(10)
Dim Temp#, Len(Text$)
~WriteFile(.hFile&, Addr(Text$), Len(Text$), Addr(Temp#), 0)
Dispose Temp#
EndProc
Syntax: OBJEKT#.PutData(MemoryBuffer&, LengthToWrite&)
Ergebnis: keins
Erklärung: Schreibt den Inhalt des angegebenen Speicherbereichs
MemoryBuffer& mit einer Länge von LengthToWrite& in die aktuelle Datei.
Proc ?_File.PutData
Parameters MemoryBuffer&, LengthToWrite&
Declare buffer#
Dim buffer#, LengthToWrite&
~WriteFile(.hFile&, MemoryBuffer&, LengthToWrite&, Addr(buffer#), 0)
Dispose buffer#
EndProc
############
# Diverses #
############
Syntax: OBJEKT#.Error()
Ergebnis: 0 oder 1
Erklärung: Gibt im Fehlerfall True (1) zurück
Z. Zt. wird nur auf ~INVALID_HANDLE_VALUE bei
OBJEKT#.Create(), OBJEKT#.Open() und OBJEKT#.Read() geprüft
Proc ?_File.Error
Return .FileError&
EndProc
Syntax: OBJEKT#.GetFile()
Ergebnis: Handle des Files
Erklärung: Hiermit kann auch nachträglich das
Handle der aktuellen Datei ermittelt werden
Proc ?_File.GetFile
Return .hFile&
EndProc
Syntax: OBJEKT#.Eof()
Ergebnis: 0 oder 1
Erklärung: Hiermit ermitteln wir ob das Ende der
Datei erreicht wurde (1) oder nicht (0)
Proc ?_File.Eof
Declare Result&
If ~SetFilePointer(.hFile&, 0, 0, ~FILE_CURRENT) < ~GetFileSize(.hFile&, 0)
Result& = 0
Else
Result& = 1
EndIf
Return Result&
EndProc
Syntax: OBJEKT#.Loc()
Ergebnis: Position
Erklärung: Gibt die aktuelle Zeiger-Position
innerhalb der Datei zurück
Proc ?_File.Loc
Return ~SetFilePointer(.hFile&, 0, 0, ~FILE_CURRENT)
EndProc
Syntax: OBJEKT#.Seek(NewPosition&)
Ergebnis:
Beschreibung: Ändert den Lese/Schreib - Zeiger innerhalb
der Datei auf die angegebene NeuePosition. Dieser
Parameter muss in Bytes angegeben werden
Proc ?_File.Seek
Parameters NewPosition&
Return ~SetFilePointer(.hFile&, NewPosition&, 0, ~FILE_BEGIN)
EndProc
Syntax: OBJEKT#.Lof()
Ergebnis: FileSize
Erklärung: LOF steht für Length Of File (Länge der Datei).
Es gibt die Länge der aktuellen Datei zurück
Proc ?_File.Lof
Return ~GetFileSize(.hFile&, 0)
EndProc
Syntax: OBJEKT#.Version()
Ergebnis: Version
Erklärung: Gibt die aktuelle Version
dieser Klasse als String wieder
Proc ?_File.Version
Return "0.5.5.18" Haupt-Version.Jahr.Monat.Tag
EndProc
|
| | | | |
| | | Hab die Unit mal geupdatet.
OBJEKT#.UseFile(hFile&) wurde entfernt. Machte leider teilweise Probleme. Um mehrere Dateien zu nutzen, ist es jetzt erforderlich für jede Datei eine neue Instanz der Klasse anzulegen. Erhöht zwar etwas den Schreibaufwand, aber es ist trotzdem weiterhin möglich fast beliebig viel Dateien gleichzeitig zu bearbeiten. Das Beispiel test3.prf wurde darauf angepaßt und auch gleich noch fehlerbereinigt. Bei der vorigen Version, sind mir auf meinem System keine Fehler aufgefallen, lediglich Rolf teilte mir diese mit. Habs ja auch hoffentlich jetzt beseitigt. Ich bin also auf das Testen von euch angewiesen.
Gruß Thomas |
| | | | |
| | | Habs kurz getestet und funzt gut.
Bei mir also Fehlerfrei.
Um nicht die Anzahl der Downloads jedes mal bei einem Update auf 0 zu setzen - nutze doch erst den Durchsuchen Knopf - und dann klicke auf neue Version.
Salve. |
| | | | |
| | | Hallo Thomas...
Bin leider (noch) kein XProfan Nutzer, deshalb werde ich erst mal auch nicht testen. Bezogen auf ~Generic_write | ~Generic_read könnte dir aber da ein Profanbug evtl. mal etwas Probleme bereiten. Schau mal in Bugnity nach... |
| | | | |
| | | [quote:1382f2518b=iF]Habs kurz getestet und funzt gut.
Bei mir also Fehlerfrei.[/quote:1382f2518b]Das Freud mich erstmal [quote:1382f2518b=iF] Um nicht die Anzahl der Downloads jedes mal bei einem Update auf 0 zu setzen - nutze doch erst den Durchsuchen Knopf - und dann klicke auf neue Version.
Salve.[/quote:1382f2518b] Habs wohl schon wieder verkehrt gemacht
[quote:1382f2518b=AH]Schau mal in Bugnity nach... [/quote:1382f2518b]Hab die entsprechenden Stellen mit OR angepaßt
Gruß Thomas |
| | | | |
| | Rolf Koch | Hi Thomas,
ja es geht jetzt!
Rolf |
| | | | |
| | | [quote:5439b97a2c]Schon wieder falsch gemacht[/quote:5439b97a2c]Gehe doch einfach mal in die Arena - dort kann man testen so viel man möchte.
Salve. |
| | | | |
| | Michael Wodrich | Nachfolgend eine Funktion mit Blockpuffer.
Proc ?_file.getstring
Declare Buffer#, Bytesread&, Text$, Text2$, FSize&, aktPos&, found&
Dim Buffer#, 1024
FSize& = ~Getfilesize(.Hfile&, 0)
aktPos& = ~Setfilepointer(.Hfile&, 0, 0, ~File_current)
While aktPos& < FSize&
~Readfile(.Hfile&, Addr(Buffer#), 1024, Addr(Bytesread&), 0)
Found& = MemPos(Buffer#,0,Chr$(0))
If Found& <> -1
Text2$ = String$(Buffer#,0)
Text$ = Text$ + Text2$
aktPos& = aktPos& + Len(Text2$) + 1
~Setfilepointer(.Hfile&, aktPos&, 0, ~File_Begin)
Break
EndIf
Found& = MemPos(Buffer#,0,Chr$(10))
If Found& <> -1
Text2$ = Char$(Buffer#,0,Found&)
Text$ = Text$ + Text2$
aktPos& = aktPos& + Len(Text2$) + 1
~Setfilepointer(.Hfile&, aktPos&, 0, ~File_Begin)
Break
EndIf
aktPos& = ~Setfilepointer(.Hfile&, 0, 0, ~File_current)
Endwhile
Dispose Buffer#
Return Translate$(Text$, Chr$(13), "")
Endproc
|
| | | Programmieren, das spannendste Detektivspiel der Welt. | 23.12.2005 ▲ |
| |
| | | Schön, das sich doch noch einer für diese Unit-Interessiert Vielleicht sollte man den Buffer auf 4096 erhöhen, nur aus dem Grunde, weil der Wert in anderen mir bekannten Funktionen auch genommen wird. Ich denke mal das wird kein Zufall sein.
Frohe Weihnacht |
| | | | |
|
AntwortenThemenoptionen | 7.316 Betrachtungen |
ThemeninformationenDieses Thema hat 4 Teilnehmer: |