How can I read from one directory all the file names?

papakosk
2018-01-03
2018-01-04
  • papakosk - 2018-01-03

    In my program I can create directory, create delete and rename csv files.
    I don't know how can I read all the csv file names and insert it in a list?

    Here is my program

    VAR
    sDirName : STRING ;
    sDirName_tmp : STRING := 'StirrupDB';
    sFirstFileName : STRING;
    sRenameFileName : STRING;
    newFileName : STRING;
    Name : STRING :='config.csv';

    sDirEntry       : STRING(1024);
    stDirInfo       : DirInfo;
    udiResult       : __XWORD;
    udiDirHandle    : RTS_IEC_HANDLE;
    udiFileHandle   : RTS_IEC_HANDLE;   
    udiReadResult   : UDINT;    
    xStartCreate        : BOOL:= FALSE; (* true, if a button is pressed *)
    xCreateDone     : BOOL:= FALSE;
    xError          : BOOL;
    ErrorCode : RTS_IEC_RESULT;
    udiCreateError: UDINT;
    udiReadError: UDINT;
    udiCloseError: UDINT;
    udiRenameError: UDINT;
    udiDeleteError1: UDINT;
    udiDeleteError2: UDINT;
    udiDirDeleteError: UDINT;
    
    xStartCreate_trig_r: R_trig;
    xStartRename_trig_r: R_trig;
    xStartDelete_trig_r: R_trig;
    ready_to_create: BOOL;
    
    DataString      :STRING(80);
    handle          :DWORD;
    sStatus         :STRING;
    iError          :INT;   (* 00 : Normal Operation    *)
                            (* 90 : Can't Open File     *)
                            (* 91 : Can't Close File    *)
                            (* 92 : Can't Write to File     *)
    pResult : POINTER TO SysFile.RTS_IEC_RESULT;
    
    r_trig_1: R_trig;
    init_1: BOOL;
    i: INT;
    arr_point: INT;
    r_trig_0 :r_trig;
    init: BOOL;
    j: INT;
    TONInst :TON;
    
    xDeleteDone: BOOL;
    xRenameDone: BOOL;
    PreviousName: STRING;
    SelectName: STRING;
    
    udcFileTime         : SYS_FILETIME;
    tCreation           : DT;
    tLastAccess     : DT;
    tLastModification   : DT;
    

    END_VAR

    xStartCreate_trig_r(CLK:= xStart_new_file);
    xStartRename_trig_r(CLK:=xStart_rename_file);
    xStartDelete_trig_r(CLK:=xStart_delete_file);

    IF xStartCreate_trig_r.Q THEN
    init := FALSE;
    name_exist := FALSE;
    xError := FALSE;
    xCreateDone := FALSE;
    ready_to_create := TRUE;
    SelectName := Name;
    END_IF

    IF xStartDelete_trig_r.Q THEN
    xDeleteDone := FALSE;
    SelectName := Name;
    END_IF

    IF xStartRename_trig_r.Q THEN
    init := FALSE;
    name_exist := FALSE;
    xError := FALSE;
    xDeleteDone := FALSE;
    xCreateDone := FALSE;
    ready_to_create := TRUE;
    newFileName := Name;
    END_IF

    IF ready_to_create AND NOT xCreateDone THEN
    ( create the complete file pathes)
    ( The file names can be adapted )
    sFirstFileName := CONCAT('/', SelectName);//'/firstTest.csv';
    sRenameFileName := CONCAT('/', newFileName);//'/rename existing .csv';

    sDirName :=  CONCAT(g_sMainDirectory, sDirName_tmp);
    sFirstFileName := CONCAT(sDirName, sFirstFileName);
    sRenameFileName := CONCAT(sDirName, sRenameFileName);
    
    (*  files are created and stored into the directory*)
    udiFileHandle := SysFileOpen(szFile:=sFirstFileName, am:=SysFile.AM_WRITE_PLUS, pResult:=ADR(ErrorCode));
    IF udiFileHandle <> RTS_INVALID_HANDLE  THEN
        SysFileClose(hFile:=udiFileHandle);
    END_IF
    
    
    (* open the directory *)
        the handle is returned and the first directory entry. Normally the first entry is "." and the second ".."*)
    udiDirHandle := SysDirOpen(szDir:= sDirName, szDirEntry:= sDirEntry, diMaxDirEntry:= SIZEOF(sDirEntry), 
                pDirInfo:= ADR(stDirInfo), pResult:= udiResult);
    
    (* Rename a file *)
    IF xStart_rename_file THEN
        udiRenameError:=SysFileRename(szOldFileName:= sFirstFileName, szNewFileName:= sRenameFileName);
        (* the test is set to done, if no error occured *)
        IF udiRenameError = 0 THEN
            xRenameDone := TRUE;
        ELSE
            xRenameDone := TRUE;
        END_IF  
        init_1 := TRUE; 
    END_IF
    
    (* Close the directory *)
    udiCloseError := SysDirClose(hDir:= udiDirHandle);
    
    // Some file information
    SysFileGetTime(szFileName:=sFirstFileName, ptFileTime:=ADR(udcFileTime));
    //creation time of the file in local time
    tCreation    := UDINT_TO_DT(udcFileTime.tCreation);
    // last access of the file
    tLastAccess  := UDINT_TO_DT(udcFileTime.tLastAccess);
    // last modification of the file
    tLastModification    := UDINT_TO_DT(udcFileTime.tLastModification);
    
    (* set to done, if no error occured *)
    IF udiCreateError = 0 AND udiCloseError = 0 AND xError = FALSE THEN
        xCreateDone := TRUE;
    ELSE
        xError := TRUE;
    END_IF
    

    END_IF

    ( Delete existing files )
    IF xStart_delete_file THEN
    ( create the complete file pathes)
    ( The file names can be adapted )
    sFirstFileName := CONCAT('/', SelectName);//'/firstTest.csv';

    sDirName :=  CONCAT(g_sMainDirectory, sDirName_tmp);
    sFirstFileName := CONCAT(sDirName, sFirstFileName);
    udiDeleteError1:=SysFileDelete(szFileName:=sFirstFileName );
    
    (* Close the directory *)
    udiCloseError := SysDirClose(hDir:= udiDirHandle);
    
    (* open the directory 
        the handle is returned and the first directory entry. Normally the first entry is "." and the second ".."*)
    udiDirHandle := SysDirOpen(szDir:= sDirName, szDirEntry:= sDirEntry, diMaxDirEntry:= SIZEOF(sDirEntry), 
                pDirInfo:= ADR(stDirInfo), pResult:= udiResult);
    
    udiDeleteError1:=SysFileDelete(szFileName:=sFirstFileName );
    (* the test is set to done, if no error occured *)
    IF udiDeleteError1 = 0 THEN
        xDeleteDone := TRUE;
    ELSE
        xDeleteDone := TRUE;
    END_IF
    xStart_delete_file := FALSE;
    

    END_IF

     
  • Lo5tNet - 2018-01-03

    In the past I have added something like the following to a loop, usually in a case statement. This is back in SP 4 Patch 2 so there might be an easier way to do it now.

    VAR
         sDirectoryList : FILE.DirList;
         sFileEntry : FILE.FILE_DIR_ENTRY; //Properties of entry in directory
         sDirHandle : CAA.HANDLE; //Open directory handle
         RunState : USINT;
    END_VAR
    CASE RunState OF
    1:  (* Find and store all files that can be loaded *)
         sDirectoryList(xExecute:=TRUE,hDir:=sDirHandle,deDirEntry=>sFileEntry);
         IF sDirectoryList.xDone THEN
              IF NOT sFileEntry.xDirectory THEN
                   //What to do if the entry is not a directory
              ELSE
                   //What to do if the entry is a directory
              END_IF
              sDirectoryList(xExecute:=FALSE); //Set directory list to false so that on next cycle it will look for the next entry in the directory.
          ELSIF sDirectoryList.eError = FILE.ERROR.NO_MORE_ENTRIES OR (sDirectoryList.xError AND sDirectoryList.eError <> FILE.ERROR.NO_MORE_ENTRIES) THEN
              //Change state or end loop
              RunState := 100;
          END_IF
    ELSE
         //End of check
    END_CASE
    
     
  • papakosk - 2018-01-04

    Thanks for your reply ..!
    Your example is not work for me.. May be my syntax is not correct.. the program stack here <<sdirectorylist.xdone>></sdirectorylist.xdone>

    IMG: Untitled.jpg

     
  • Lo5tNet - 2018-01-04

    I notice that your udiDirHandle is empty so something is not setup correctly there. I haven't played around much with the way you are doing it but here is a working example. This example will count the number of files and directories in a specific location defined by "sDirectory". In the below example I was not getting the directory '.' to show up but it would count '..' as the first directory. If you have more time and care you can probably look into it. There are a lot of optimizations you can do do speed the search up but this will get you running.

    IMG: Vars.PNG

    IMG: Program.PNG

     

Log in to post a comment.