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] [EINKLAPPEN]
Type TDir Field _pDir:Int Field _fOpened:Byte,_fIndexed:Byte,_fIndexedSubDirs:Byte Field _Path:String,_DirName:String,_FullPath:String Field _sDefaultAccess:Byte Field _rgFiles:TList,_rgSubDirs:TList Field _pActualLink:TLink,_pActualDir:TLink
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
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
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
Method GetIndex:TList() Return Self._rgFiles End Method
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
Method ClearIndex(fRefresh:Byte=False) Self._fIndexed=False Self._pActualLink=Null Self._rgFiles.Clear() If fRefresh=True Then Self.Refresh() End Method
Method RefreshIndex(fRefresh:Byte=False) Self.ClearIndex(fRefresh) Self.IndexFiles() End Method
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
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
Method ClearDirIndex(fRefresh:Byte=False) Self._fIndexedSubDirs=False Self._pActualDir=Null ClearList(Self._rgFiles) If fRefresh=True Then Self.Refresh() End Method
Method RefreshDirIndex(fRefresh:Byte=False) Self.ClearDirIndex(fRefresh) Self.IndexDirs() End Method
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
Method Open() Self._pDir=ReadDir(_FullPath) Self._fOpened=True End Method
Method Close() CloseDir(Self._pDir) Self._fOpened=False End Method
Method Refresh() Self.Close() Self.Open() End Method
Method FileList:TList() Return Self._rgFiles End Method
Method DirectoryList:TList() Return Self._rgSubDirs End Method
Method Stream:Int() Return Self._pDir End Method End Type
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
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
Method Delete() Self.Close() End Method
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
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
Method Close() Self._fOpened=False CloseStream(Self._pFile) DebugLog "Success!" End Method
Method Refresh() If Self._fOpened=False Then Return Self.Close() Self.Open() End Method
Method Stream:TStream() Return Self._pFile End Method
Method File:TStream() Return Self._pFile End Method
Method Name:String() Return Self._rgchName End Method End Type
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
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] [EINKLAPPEN] SuperStrict
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" 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 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" 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 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 ). 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...
|