Types TDir und TFile

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

 

n-Halbleiter

Betreff: Types TDir und TFile

BeitragMo, Feb 08, 2010 23:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Guten Abend.

Ich habe aus meinem aktuellen Projekt zwei Types extrahiert und dokumentiert, die ich euch gerne präsentieren möchte.

Es handelt sich um die Types TDir und TFile. Die Nutzweise sollte anhand des Namens klar werden, denke ich. An sich sind es nur einfache gewrappte Funktionen und Werte, jedoch habe ich einige Möglichkeiten eingefügt, die die Sache delikat machen dürften: Es gibt pro TDir-Objekt zwei Listen: Eine mit sämtlichen Unterordnern (ebenfalls TDir) und allen Dateien im Ordner (alle TFile). Für sämtliche relevanten Eigenschaften gibt es ebenfalls Wrappermethoden, da die Nomenklatur meinerseits evtl. erstmal merkwürdig erscheinen mag: Ich benenne sämtliche Member von Types mit einem Unterstrich davor, Globalen und Konstanten erhalten ein G_ bzw. C_. Außerdem ist z.T. ungarische Notation verbaut, da es - für mich - die Lesbarkeit und Verständlichkeit erhöht. Ich habe ein Präfix hinzugefügt, das ich jedoch auch dokumentiert habe.

Lange Rede, kurzer Sinn, hier ist die Includedatei "TDir.bmx". BlitzMax: [AUSKLAPPEN]
Rem Imports needed:
BRL.FileSystem
BRL.LinkedList
End Rem


Rem
File system extension. This Code provides some useful functions for handling directories and files.
End Rem


Rem
Added another prefix For hungarian notation: s for state
All the states are listed in constant variables
End Rem


'Directory Object
Type TDir

Field _pDir:Int
Field _fOpened:Byte,_fIndexed:Byte,_fIndexedSubDirs:Byte
Field _Path:String,_DirName:String,_FullPath:String
Field _sDefaultAccess:Byte
'Note: Those "rg" are not really arrays...
Field _rgFiles:TList,_rgSubDirs:TList
Field _pActualLink:TLink,_pActualDir:TLink

Rem
Constructor
End Rem

Function Create:TDir(Path:String,fOpen:Byte=True,fIndex:Byte=False, fIndexDirs:Byte=False,sAccess:Byte=TFile.C_Access_Read)
Local Dir:TDir=New TDir
Dir.Init(Path,fOpen,fIndex,fIndexDirs,sAccess)
Return Dir
End Function

Rem
Initialisation Method, this one sets all the needed values.
End Rem

Method Init(Path:String,fOpen:Byte=True,fIndex:Byte=False, fIndexDirs:Byte=False,sAccess:Byte=TFile.C_Access_Read)
Path:+".DDD"
Self._DirName=StripAll(Path)
Self._Path=RealPath(StripExt(Path))
Self._FullPath=Self._Path
Self._sDefaultAccess=sAccess
If fOpen=True Then Self.Open()
If fIndexDirs=True Then Self.IndexDirs()
If fIndex=True Then Self.IndexFiles()
End Method

'The raw NextFile thing
Rem
Returns the Next file in the directory.
End Rem

Method NFile:TFile()
Local Str:String=Self._FullPath+"/"+NextFile(Self._pDir)
If Str="" Then Return Null
If FileType(Str)<>FILETYPE_FILE Then Return Null
If Self._fOpened=True Then Return File_Create(Str,Self._sDefaultAccess)
End Method

'General Methods for indexing
Rem
Returns the list with all the indexed files. You could also write "MyDir._rgFiles", but this may be more beautiful.
End Rem

Method GetIndex:TList()
Return Self._rgFiles
End Method

'Methods to index all files in the directory
Rem
Indexes all the files.
End Rem

Method IndexFiles()
Local File:TFile=Self.NFile()
Self._fIndexed=True
Self._rgFiles=CreateList()
While File<>Null
Self._rgFiles.AddLast(File)
File=Self.NFile()
Wend
Self._pActualLink=Self._rgFiles.FirstLink()
End Method

Rem
Clears the filelist.
End Rem

Method ClearIndex(fRefresh:Byte=False)
Self._fIndexed=False
Self._pActualLink=Null
Self._rgFiles.Clear()
If fRefresh=True Then Self.Refresh()
End Method

Rem
Refreshes the filelist.
End Rem

Method RefreshIndex(fRefresh:Byte=False)
Self.ClearIndex(fRefresh)
Self.IndexFiles()
End Method

Rem
Returns the Next indexed file.
End Rem

Method NextIndex:TFile()
If Self._fIndexed=False Then Return Null
If Self._pActualLink=Null Then Return Null
If Self._pActualLink._succ=Null Then Return Null
Self._pActualLink=Self._pActualLink._succ
Return TFile(Self._pActualLink._pred.Value())
End Method

'Methods to index all Subdirs in the directory
Rem
Indexes all subdirectories.
End Rem

Method IndexDirs()
Local Dir:String=Self._FullPath+"/"+NextFile(Self._pDir)
Self._fIndexedSubDirs=True
Self._rgSubDirs=CreateList()
While Dir<>""
If FileType(Dir)=FILETYPE_DIR
Self._rgFiles.AddLast(Dir_Create(Dir,False))
End If
Dir=Self._FullPath+"/"+NextFile(Self._pDir)
Wend
Self._pActualDir=Self._rgSubDirs.FirstLink()
End Method

Rem
Clears the whole list of directories.
End Rem

Method ClearDirIndex(fRefresh:Byte=False)
Self._fIndexedSubDirs=False
Self._pActualDir=Null
ClearList(Self._rgFiles)
If fRefresh=True Then Self.Refresh()
End Method

Rem
Refreshes the list of the directories.
End Rem

Method RefreshDirIndex(fRefresh:Byte=False)
Self.ClearDirIndex(fRefresh)
Self.IndexDirs()
End Method

Rem
Returns the Next indexed directory in the list.
End Rem

Method NextDir:TDir()
If Self._fIndexedSubDirs=False Then Return Null
If Self._pActualDir=Null Then Return Null
If Self._pActualDir._succ=Null Then Return Null
Self._pActualDir=Self._pActualDir._succ
Return TDir(Self._pActualDir._pred.Value())
End Method

'General Methods
Rem
Opens the directory.
End Rem

Method Open()
Self._pDir=ReadDir(_FullPath)
Self._fOpened=True
End Method

Rem
Closes the directory.
End Rem

Method Close()
CloseDir(Self._pDir)
Self._fOpened=False
End Method

Rem
Refreshes the directory. The "progress" of NextFile will be set to the beginning.
End Rem

Method Refresh()
Self.Close()
Self.Open()
End Method

Rem
Returns the list of all the indexed files. The related Field is "_rgFiles".
End Rem

Method FileList:TList()
Return Self._rgFiles
End Method

Rem
Returns the list of the indexed directories. The related Field is "_rgSubDirs".
End Rem

Method DirectoryList:TList()
Return Self._rgSubDirs
End Method

'General Method for handling the directory stream
Rem
Returns the Dirstream
End Rem

Method Stream:Int()
Return Self._pDir
End Method

End Type

'File Object, may be used by TDir. This depends on whether you index the files of a directory Or Not.
Type TFile

Const C_Access_Read:Byte=1
Const C_Access_Write:Byte=2

Field _pFile:TStream
Field _rgchName:String
Field _fOpened:Byte
Field _sAccess:Byte

Rem
Constructor
End Rem

Function Create:TFile(Name:String,sAccess:Byte=TFile.C_Access_Read,fOpen:Byte=True)
Local File:TFile=New TFile
File.Init(Name,sAccess,fOpen)
Return File
End Function

Rem
Clean destructor
End Rem

Method Delete()
Self.Close()
End Method

Rem
Initialisation Method
End Rem

Method Init(Name:String,sAccess:Byte=TFile.C_Access_Read,fOpen:Byte=True)
Self._rgchName=Name
Self._sAccess=sAccess
If fOpen=True Then Self.Open()
End Method

Rem
Opens the file with the specified accessmode.
End Rem

Method Open()
Self._fOpened=True
Select Self._sAccess
Case C_Access_Read
Self._pFile=ReadFile(Self.Name())
Case C_Access_Write
Self._pFile=WriteFile(Self.Name())
End Select
End Method

Rem
Closes the file.
End Rem

Method Close()
Self._fOpened=False
CloseStream(Self._pFile)
DebugLog "Success!"
End Method

Rem
Refreshes the stream. This means closing with subsequent opening.
End Rem

Method Refresh()
If Self._fOpened=False Then Return
Self.Close()
Self.Open()
End Method

Rem
Returns the stream. You could also write "MyFileVar._pFile", but this may be more beautiful.
End Rem

Method Stream:TStream()
Return Self._pFile
End Method

Rem
The same as with Method "Stream".
End Rem

Method File:TStream()
Return Self._pFile
End Method

Rem
Returns the name of the file. You could also write "MyFileVar._rgchName", but this may be more easy.
End Rem

Method Name:String()
Return Self._rgchName
End Method

End Type

'Wrapped functions For creation
Rem
The constructor For a directory Object.
End Rem

Function Dir_Create:TDir(Path:String,fOpen:Byte=True,fIndex:Byte=False, fIndexDirs:Byte=False,sAccess:Byte=TFile.C_Access_Read)
Return TDir.Create(Path,fOpen,fIndex,fIndexDirs,sAccess)
End Function

Rem
The constructor For a file Object.
End Rem

Function File_Create:TFile(Name:String,sAccess:Byte=TFile.C_Access_Read, fOpen:Byte=True)
Return TFile.Create(Name,sAccess,fOpen)
End Function


Da ein Archiveintrag ja noch ein Beispiel beinhalten soll, habe ich noch schnell eine kleine Shell gecodet, die jedoch nicht das gesamte Potential der Types TDir und TFile ausnutzt. BlitzMax: [AUSKLAPPEN]
SuperStrict

Rem
Added another prefix for hungarian notation: s for state
All the states are listed in constant variables
End Rem


Include "TDir.bmx"

Const sMode_Cmd:Byte=0
Const sMode_Input:Byte=1

Local Cmd:String
Global sMode:Byte=0
Global File:TFile
Global Dir:TDir

Repeat
Select sMode
Case sMode_Cmd
Cmd=Input(CurrentDir()+"> ")
ProcessInput(Cmd)
Case sMode_Input
Cmd=Input("")
If File<>Null
If Lower(Cmd)="$back"
File.Close()
File=Null
sMode=sMode_Cmd
Else
WriteLine(File.Stream(),Cmd)
End If
End If
End Select
Forever

Function ProcessInput(rgch:String)
Local i:Int
Local ichLast:Int

Local rgchLow:String=Lower(rgch)+" "
Local ichFirstSpace:Int=Instr(rgchLow," ")
Local cch:Int=rgch.length

Local rgchCmd:String=rgchLow[0..ichFirstSpace-1]
Local rgchArgs:String=rgchLow[ichFirstSpace..cch]

Local cchArgs:Int
Local ichArg:Int[]
Local rgchArg:String[]

Local rgchTemp:String

Select rgchCmd
Case "end"
End
Case "file"
'Begin routine: Argument parsing
cchArgs=2
ichArg=New Int[cchArgs]
rgchArg=New String[cchArgs]
ichLast=1
For i=0 To cchArgs-1
ichArg[i]=Instr(rgchArgs," ",ichLast)
If i=cchArgs-1
rgchArg[i]=Trim(rgchArgs[ichLast-1..cch])
Else
rgchArg[i]=Trim(rgchArgs[ichLast-1..ichArg[i]])
End If
ichLast=ichArg[i]
Next
'End routine
Select rgchArg[0]
Case "write"
File=TFile.Create(rgchArg[1],TFile.C_Access_Write)
If File=Null Or File.Stream()=Null Then Print "There is no file called "+rgchArg[1];Return
sMode=sMode_Input
Case "read"
File=TFile.Create(rgchArg[1],TFile.C_Access_Read)
If File=Null Or File.Stream()=Null Then Print "There is no file called "+rgchArg[1];Return
While Not Eof(File.Stream())
Print ReadLine(File.Stream())
Wend
File.Close()
File=Null
End Select
Case "cd"
'Begin routine: Argument parsing
cchArgs=1
ichArg=New Int[cchArgs]
rgchArg=New String[cchArgs]
ichLast=1
For i=0 To cchArgs-1
ichArg[i]=Instr(rgchArgs," ",ichLast)
If i=cchArgs-1
rgchArg[i]=Trim(rgchArgs[ichLast-1..cch])
Else
rgchArg[i]=Trim(rgchArgs[ichLast-1..ichArg[i]])
End If
ichLast=ichArg[i]
Next
'End routine
ChangeDir rgchArg[0]
Case "dir"
Dir=TDir.Create(CurrentDir())
rgchTemp=NextFile(Dir.Stream())
While rgchTemp<>""
Print rgchTemp+RepeatString(" ",70-rgchTemp.length)+"Type: "+FileTypeToString(FileType(rgchTemp))
rgchTemp=NextFile(Dir.Stream())
Wend
End Select
End Function

Function RepeatString:String(Str:String,Count:Int)
Local newString:String=""
While Count<>0
If (Count & 1)<>0
newString=newString+Str
EndIf
Count=Count Shr 1
Str:+Str
Wend
Return newString
End Function

Function FileTypeToString:String(l:Int)
Select l
Case 0
Return "Inexistent"
Case FILETYPE_FILE
Return "File"
Case FILETYPE_DIR
Return "Directory"
End Select
End Function


Falls es noch Fragen bezüglich der Nutz- und Verarbeitbarkeit der Codes geben, bitte ich darum, mir dies mitzuteilen.

An die Mods und Admins: Wenn ich mit diesem Beitrag gegen Codearchiv-Regeln verstoßen sollte, bitte ich um einen Hinweis (auch wenn ich denke, dass ihr das ja sowieso immer macht Wink). Meiner Meinung nach ist dies kein komplettes Modul, da es ja nur bedingt tolle neue Features einführt bzw. sie einfacher zu handhaben macht.

EDIT: Nachdem ich mich versehentlich verklickt hatte (auf "Absenden" anstatt "Vorschau"), habe ich nun noch versucht, das Boardlayout irgendwe zu retten. Hat nun funktioniert... Wink

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group