File system bits and pieces

Share your advanced PureBasic knowledge/code with the community.
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

File system bits and pieces

Post by utopiomania »

Code updated For 5.20+

I'm busy translating a few programs to PureBasic and would like to post some tiny bits of them for testing
and in case you can use any of it.

These three procedures are meant to be 'file type aware', REM/UNREM in the event handler to check out
each of them. The 'docs' are to be found in the remarks in the procedures themselves. :wink:

Code: Select all

;FILESYSTEM PROCEDURES

;DECLARATIONS
Declare GetDirEntries(Path.s,Ext.s,Dirs,Excl)
Declare GetAllDirEntries(Path.s,Ext.s,I,N,Dirs,Excl)
Declare FindFileTypesInDir(Path.s,Ext.s,Excl)
Declare GetDirsWithFileTypes(Path.s,Ext.s,Excl)
Declare.s GetAppDir()

#MaxDirEntries=128000
Dim DirEntries.s(#MAxDirEntries)

Procedure GetDirEntries(Path.s,Ext.s,Dirs,Excl)
  ;Fills in the array DirEntries with directory entries in path.
  ;Lists all(Ext.s="") or some(Ext.s=".rtf;.htm;" etc.) filetypes.
  ;Includes directories if Dirs=1.
  ;Excludes hidden and system entries if Excl=1.
  If ExamineDirectory(0,Path.s,"*.*")
    Repeat
      WindowEvent()
      FileType=NextDirectoryEntry(1)
      If FileType
        Name.s=DirectoryEntryName(1)
        Attr=DirectoryEntryAttributes(1)
        Incl=1
        If Excl And (Attr&#PB_FileSystem_Hidden)|(Attr&#PB_FileSystem_System)
          ;Hidden or system file, do not include
          Incl=0
        EndIf
        If Incl
          ;Entry attributes ok, entry eligible for inclusion
          If FileType=2
            ;The entry is a directory
            If Dirs And Name.s<>"." And Name.s<>".."
              ;To be included and is not a dot entry
              Shared DirEntries()
              DirEntries.s(I)=Path.s+Name.s+"\"
              I+1
              DirEntries.s(I)=""
            EndIf
          Else
            ;The entry is a file
            If Ext.s
              ;List files with some extensions
              FileExt.s="."+GetExtensionPart(Name.s)+";"
              If Len(FileExt.s) And FindString(LCase(Ext.s),LCase(FileExt),1)
                DirEntries.s(I)=Path.s+Name.s
                I+1
              EndIf
            Else
              ;List files with all extensions
              DirEntries.s(I)=Path.s+Name.s
              I+1
              DirEntries.s(I)=""
            EndIf
          EndIf
        EndIf
      EndIf
    Until FileType=0
  EndIf
  ProcedureReturn I
EndProcedure

Procedure GetAllDirEntries(Path.s,Ext.s,I,N,Dirs,Excl)
  ;Fills in the array DirEntries with directory entries in path
  ;and in subdirectories of path.
  ;Lists all(Ext.s="") or some(Ext.s=".rtf;.htm;" etc.) filetypes.
  ;Includes directories if Dirs=1.
  ;Excludes hidden and system entries if Excl=1.
  If ExamineDirectory(N,Path.s,"*.*")
    Repeat
      WindowEvent()
      FileType=NextDirectoryEntry(N)
      If FileType
        Name.s=DirectoryEntryName(N)
        Attr=DirectoryEntryAttributes(N)
        Incl=1
        If Excl And (Attr&#PB_FileSystem_Hidden)|(Attr&#PB_FileSystem_System)
          ;Hidden or system file, do not include
          Incl=0
        EndIf
        If Incl
          ;Entry attributes ok, entry eligible for inclusion
          If FileType=2
            ;The entry is a directory
            If Name.s<>"." And Name.s<>".."
              ;Open it
              I=GetAllDirEntries(Path.s+Name.s+"\",Ext.s,I,N+1,Dirs,Excl)
              ;Returned,  use the current directory
              ;                   UseDirectory(N)
              If Dirs
                ;Include directory entries
                Shared DirEntries()
                DirEntries.s(I)=Path.s+Name.s+"\"
                I+1
                DirEntries.s(I)=""
              EndIf
            EndIf
          Else
            ;The entry is a file
            If Ext.s
              ;List files with some extensions
              FileExt.s="."+GetExtensionPart(Name.s)+";"
              If Len(FileExt.s) And FindString(LCase(Ext.s),LCase(FileExt),1)
                DirEntries.s(I)=Path.s+Name.s
                I+1
                DirEntries.s(I)=""
              EndIf
            Else
              ;List files with all extensions
              DirEntries.s(I)=Path.s+Name.s
              I+1
              DirEntries.s(I)=""
            EndIf
          EndIf
        EndIf
      EndIf
    Until FileType=0
  EndIf
  ProcedureReturn I
EndProcedure

Procedure GetDirsWithFileTypes(Path.s,Ext.s,Excl)
  ;Fills in the array DirEntries with directory entries in path
  ;that contains filetypes listed in Ext.s(Ext.s=".rtf;.htm;" etc.).
  ;Excludes hidden and system entries if Excl=1.
  If ExamineDirectory(N,Path.s,"*.*")
    Repeat
      FileType=NextDirectoryEntry(n)
      If FileType
        Name.s=DirectoryEntryName(n)
        Attr=DirectoryEntryAttributes(n)
        Incl=1
        If Excl And (Attr&#PB_FileSystem_Hidden)|(Attr&#PB_FileSystem_System)
          ;Hidden or system file, do not include
          Incl=0
        EndIf
        If Incl
          ;Entry attributes ok, entry eligible for inclusion
          If FileType=2
            ;The entry is a directory
            If Name.s<>"." And Name.s<>".."
              ;Open it and look for some filetypes
              If FindFileTypesInDir(Path.s+Name.s+"\",Ext.s,N+1)
                ;Found a filetype in or under it
                Shared DirEntries()
                DirEntries(I)=Path.s+Name.s+"\"
                I+1
                DirEntries.s(I)=""
              EndIf
              
            EndIf
          Else
            ;The entry is a file
            ;Store it ????
          EndIf
        EndIf
      EndIf
    Until FileType=0
  EndIf
  ProcedureReturn I
EndProcedure

Procedure FindFileTypesInDir(Path.s,Ext.s,N)
  ;Searches Path.s recursively and returns 1 if it contains
  ;filetypes listed in Ext.s(Ext.s=".rtf;.htm;" etc.).
  ;Called by GetDirsWithFileTypes() to probe for filetypes.
  If ExamineDirectory(N,Path.s,"")
    Repeat
      FileType=NextDirectoryEntry(n)
      If FileType
        Name.s=DirectoryEntryName(n)
        If FileType=2
          ;The entry is a directory
          If Name.s<>"." And Name.s<>".."
            ;Open it and look for some filetypes
            If FindFileTypesInDir(Path.s+Name.s+"\",Ext.s,N+1)
              ;Found, unwind
              ProcedureReturn 1
            EndIf
            
          EndIf
        Else
          ;The entry is a file
          FileExt.s="."+GetExtensionPart(Name.s)+";"
          If Len(FileExt.s) And FindString(LCase(Ext.s),LCase(FileExt),1)
            ;Found, unwind
            ProcedureReturn 1
          EndIf
        EndIf
      EndIf
    Until FileType=0
  EndIf
  ProcedureReturn 0
EndProcedure

Procedure.s GetAppDir()
  ;Returns the current application directory
  AppDir.s=Space(255) 
  GetCurrentDirectory_(255,@AppDir.s)
  If Right(AppDir.s,1)<>"\"
    AppDir.s+"\"
  EndIf
  ProcedureReturn AppDir.s
EndProcedure
;FILESYSTEM PROCEDURES END

;FILESYSTEM PROCEDURES TESTPROGRAM
;CONTROL ID'S
Enumeration
  #IDWinMain
  #IDEdtDir
  #IDBtnBrowse
  #IDLstDir
EndEnumeration

;MAIN WINDOW
Flags=#PB_Window_SystemMenu|#PB_Window_ScreenCentered
OpenWindow(#IDWinMain,0,0,800,400,"File System Procedures",Flags)

;MAIN WINDOW CONTROLS

StringGadget(#IDEdtDir,10,10,710,25,Path.s)
ButtonGadget(#IDBtnBrowse,730,10,60,25,"Browse")
ListViewGadget(#IDLstDir,10,45,780,345)

Path.s=GetAppDir()

;EVENT LOOP
Repeat
  EventID=WaitWindowEvent()
  Select EventID
    Case #PB_Event_CloseWindow
      Exit=1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #IDBtnBrowse
          Path.s=PathRequester("",Path.s)
          If Path.s
            SetGadgetText(#IDEdtDir,Path.s)
            
            I=0:N=0
            ;           Unrem to test procedure #1
            ;            GetDirEntries(Path.s,"",0,1)
            
            ;           Unrem to test procedure #2
            GetAllDirEntries(Path.s,".txt;.rtf;.htm;.pb;",I,N,0,1)
            
            ;           Unrem to test procedure #3
            ;            GetDirsWithFileTypes(Path.s,".lnk;.url;",1)
            I=0
            While DirEntries.s(I)
              WindowEvent()
              AddGadgetItem(#IDLstDir,-1,DirEntries.s(I))
              I+1
            Wend
            AddGadgetItem(#IDLstDir,-1,Str(I)+" entries found.")
          EndIf
      EndSelect
  EndSelect
Until Exit
End

Last edited by utopiomania on Fri Jun 10, 2005 5:17 pm, edited 1 time in total.
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1282
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Post by Paul »

Certainly not a good idea to use GetCurrentDirectory_() for App path since current directory will change when you start using file commands or requesters.

Use GetModuleFileName_()

Code: Select all

Procedure.s GetAppDir()
  AppDir.s=Space(512)
  GetModuleFileName_(0,@AppDir,512)
  AppDir=GetPathPart(AppDir)
  If Right(AppDir,1)<>"\":AppDir+"\":EndIf
  ProcedureReturn AppDir
EndProcedure
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

Thanks. I use it once here to get to my applications startup folder. What's wrong with that? :?:
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

I just found out one thing that I didn't find in the manual. The recursive procedure GetAllDirEntries()
above, and the While DirEntries() ... AddgadgetItem().. in the message loop is so intense they freezes the
gadgets until finished, but inserting a WindowEvent() at the right places in the loops allows them to
update even at 100% CPU! :)

This doesn't allow me to handle messages in the message loop while the procedure runs, but it allows
Windows to update the gadgets involved in real time. Maybe this could be added to the manual, because it
can solve some problems much simpler than using threads to do the same. :?:
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

I just finished this, it's supposed to rename files according to a file's filetime and a user supplied format
string accepting a few two character Ucase tokens, and passing nearly everything else on except illegal
characters. :)

Code: Select all

;DECLARATIONS
Declare.s FileTimeToFileName(Path.s,Format.s,When)
Declare.s GetAppDir()


Procedure.s FileTimeToFileName(Path.s,Format.s,When)
  Time.FILETIME
  LocTime.FILETIME
  SysTime.SYSTEMTIME        
  
  Id=ReadFile(0,Path)
  
  Select When
    Case 0 ;Created    
      GetFileTime_(Id,Time,0,0)
    Case 1 ;Accessed
      GetFileTime_(Id,0,Time,0)
    Case 2 ;Modified
      GetFileTime_(Id,0,0,Time)            
  EndSelect
  
  FileTimeToLocalFileTime_(Time,LocTime)
  FileTimeToSystemTime_(LocTime,SysTime)
  CloseFile(0)
  
  For I=1 To Len(Format) Step 2
    Select Mid(Format,I,2)
      Case "YR" ;Year
        Name.s+Right(Str(SysTime\wYear),4)      
      Case "MN" ;Month
        Name.s+Right("0"+Str(SysTime\wMonth),2)
      Case "DY" ;Day
        Name.s+Right("0"+Str(SysTime\wDay),2)
      Case "HR" ;Hour
        Name.s+Right("0"+Str(SysTime\wHour),2)           
      Case "MI" ;Minute
        Name.s+Right("0"+Str(SysTime\wMinute),2)
      Case "SE" ;Second
        Name.s+Right("0"+Str(SysTime\wSecond),2)  
      Case "MS" ;Millisecond
        Name.s+Right("0"+Str(SysTime\wMilliSeconds),2)  
      Default ;Pass on
        If FindString(Chr(34)+"\/*<>|#.",Mid(Format,I,1),1)=0
          Name.s+Mid(Format,I,1)
          I-1          
        EndIf          
    EndSelect
  Next
  Name+"."+GetExtensionPart(Path.s)

  ProcedureReturn LTrim(Name)
EndProcedure


Procedure.s GetAppDir()
  ;Returns the current application directory
  AppDir.s=Space(255)  
  GetCurrentDirectory_(255,@AppDir.s)
  If Right(AppDir.s,1)<>"\"
    AppDir.s+"\"
  EndIf
  ProcedureReturn AppDir.s
EndProcedure


;TEST
Path.s=OpenFileRequester("Pick a filename",GetAppDir(),"",0)

; !
Format.s="..\/<>*#|. YR-MN-DY_HR:MI:SE:MS This is the new filename :) "

MessageRequester(GetFilePart(Path.s),FileTimeToFileName(Path.s,Format.s,0))
End



; IDE Options = PureBasic v3.94 Beta 1 - Windows x86
; EnableXP
; Executable = C:\Programmation\PureBasic\Examples\FileSystem.exe
Post Reply