reading recursive

Posted by goo on 26-Feb-2018 06:52

I am trying to read all sub directories from a given directory, and doing that recursive. I am getting a problem with an array that I get back from System.IO.Directory:GetDirectories(ipDirectory).

Could I make an instance of String and add it to that instead of using cDirectories as char ... as I do? 

is there an easier way of doing what I want? 

I want to add all directories into a temp-table with a parent pointer.

//Geir Otto

procedure checkDirectory :
  define input param ipDirectory as char no-undo.  
define input param ipParentId as int no-undo.
def var cDirectories as char extent no-undo.
def var ixx as int no-undo.

ix = ix + 1.
bDirectoryExist = System.IO.Directory:Exists(ipDirectory).
if not bDirectoryExist then do:
return ?.
end.
create ttDirectory.
assign
ttDirectory.iDirectoryId = ix
ttDirectory.cDirectoryName = ipDirectory
ttDirectory.iParentDirectory = ipParentId
.
cDirectories = System.IO.Directory:GetDirectories(ipDirectory).
do ixx = 1 to extent(cDirectories):
run checkDirectory(cDirectories[ixx],ttDirectory.iDirectoryId).
end.
if ix gt 300 then stop.
end.

Posted by Laura Stern on 26-Feb-2018 08:27

You are getting a problem?  You didn't say what the problem is!

Is cDirectories not being populated properly from that assignment statement?

  cDirectories = System.IO.Directory:GetDirectories(ipDirectory).

You are getting back a String[] from .NET and we would be converting that to a CHAR EXTENT in the ABL.  You could also just leave it as the .NET class, i.e., define cDirectories as a "System.String[]", and get the values out of it using:

  cDirectories:GetValue[ixx] (except this index has to be 0 based, not 1).

And I don't understand your sentence:

  Could I make an instance of String and add it to that instead of using cDirectories as char ... as I do?

Make an instance of a String (from what?) add it to "that" (what is "that").

All Replies

Posted by Laura Stern on 26-Feb-2018 08:27

You are getting a problem?  You didn't say what the problem is!

Is cDirectories not being populated properly from that assignment statement?

  cDirectories = System.IO.Directory:GetDirectories(ipDirectory).

You are getting back a String[] from .NET and we would be converting that to a CHAR EXTENT in the ABL.  You could also just leave it as the .NET class, i.e., define cDirectories as a "System.String[]", and get the values out of it using:

  cDirectories:GetValue[ixx] (except this index has to be 0 based, not 1).

And I don't understand your sentence:

  Could I make an instance of String and add it to that instead of using cDirectories as char ... as I do?

Make an instance of a String (from what?) add it to "that" (what is "that").

Posted by goo on 26-Feb-2018 09:09

I am getting Uninitialize array used as source of  assignment....

Posted by goo on 26-Feb-2018 09:09

Progress error(14906)

Posted by goo on 26-Feb-2018 09:14

Sorry, I am not that familiar with .net semantic. Forget what I said :-) I am trying to define the cString as char extent, several times  (recursive) and it seems like that is the problem?

Posted by goo on 26-Feb-2018 09:35

This seems to work :-) Thanks Laura

procedure checkDirectory :

 define input param ipDirectory as char no-undo.

 define input param ipParentId  as int  no-undo.

 def var cDirectory as char no-undo.

 def var cText as "System.String[]" no-undo.

 def var ixx as int no-undo.

 ix = ix + 1.

 bDirectoryExist = System.IO.Directory:Exists(ipDirectory).

 if not bDirectoryExist then do:

   MESSAGE ipDirectory ' eksisterer ikke'

   VIEW-AS ALERT-BOX.

   return ?.

 end.

 create ttDirectory.

 assign

   ttDirectory.iDirectoryId     = ix

   ttDirectory.cDirectoryName   = ipDirectory

   ttDirectory.iParentDirectory = ipParentId

   .

 assign

   cText = System.IO.Directory:GetDirectories(ipDirectory)

   .

 cDirectory = cText:GetValue(ixx) no-error.

 if not System.IO.Directory:Exists(cDirectory) then return.

 do ixx = 0 to cText:Length:

   cDirectory = cText:GetValue(ixx) no-error.

        MESSAGE ixx ' - inne' cDirectory

   VIEW-AS ALERT-BOX.

   run checkDirectory(cDirectory,ttDirectory.iDirectoryId).  

 end.

 if ix gt 300 then stop.

end.

Posted by Laura Stern on 26-Feb-2018 09:51

The problem is that when you get down to the bottom level where there are no more directories, System.IO.Directory:GetDirectories(ipDirectory) returns an empty array (an array with no elements).  We cannot convert that into an ABL array, as there is no such thing as an array with no elements in the ABL.  

So before you do that assignment, you need to get the System.String[] into a variable (defined as "System.String[]") and check its Length property.  If the length is 0, then you know you need to stop.  

And since you are already getting it as a .NET object, you might as well just leave it as that, instead of converting it to an ABL array, as I said before.  Just use it like an object - by calling its method GetValue(ix) to get the element you want (making sure ix is based at 0).  If you're going to use .NET to do things, it would be good if you learned how to use the objects you get back from .NET.

Posted by bronco on 26-Feb-2018 10:43

@goo, have you considered using 4GL?

Posted by goo on 26-Feb-2018 12:50

Nups, I want to learn using more of the stuff related to .Net and windows, so I found that I need to try. And it works :-) I now  have converted it to oo, so it is even more simple.

Posted by Patrick Tingen on 26-Feb-2018 13:12

In this case, your program runs fine, but when doing recursive stuff that includes tt handling, you'd better use buffers for your temp-table. The way you do it now causes the temp-table to be scoped to the procedure as a whole and you want it to scope to the procedure itself.

As I said, your program will run fine, but that is more or less accidental. If you wanted to do something with the temp-table record after your recursive call to checkDirectory, then it will fail. Try to replace 'run checkDirectory' with the code below and see what it shows.

   MESSAGE 1 ttDirectory.cDirectoryName VIEW-AS ALERT-BOX.
   RUN checkDirectory(cDirectory, ttDirectory.iDirectoryId).  
   MESSAGE 2 ttDirectory.cDirectoryName VIEW-AS ALERT-BOX.

This thread is closed