Page 1 of 1
File handling
Posted: Sat Sep 28, 2013 4:02 pm
by Robert
Hi
I always assumed that if I wrote:
Code: Select all
loc := Files.dir.This ("D:\Data\ProjectX");
for example, and the path did not exist, that I would get loc = NIL.
However that does not seem to be the case.
What is the easiest way to test if a specific path exists?
Thanks
Robert
Re: File handling
Posted: Sat Sep 28, 2013 4:20 pm
by Ivan Denisov
You can use
Files.dir.LocList for that.
Example
Code: Select all
MODULE PrivTest;
IMPORT Log, Files;
PROCEDURE Do*;
VAR info: Files.LocInfo;
BEGIN
info := Files.dir.LocList(Files.dir.This ("D:\Data\ProjectX"));
IF info = NIL THEN
Log.String("No such folder"); Log.Ln
ELSE
WHILE info.next # NIL DO
Log.String(info.name); Log.Ln;
info := info.next
END
END
END Do;
END PrivTest.
Re: File handling
Posted: Wed Nov 18, 2015 9:55 pm
by Robert
Ivan
Thanks for the suggestion, but I don't think it works!
The "No such folder" string does not tell me that the stated folder does not exist, but rather that it has no sub-folders.
I know how to solve the problem (ie parse the folder string to strip off the last level, then call LocList, then scan the list for the stripped off bottom level).
The purpose of my question was to know if there is a simpler way.
Sorry for long (over two years) time to reply. I guess that this is not my most important problem!
Cheers,
Robert
Re: File handling
Posted: Thu Nov 19, 2015 9:11 pm
by Robert
I tried another
simple approach to check if a directory path exists:
Code: Select all
loc := Files.dir.This ("D:\Data\ProjectX");
IF loc.res = 0 ...
because the Files Docu says that loc.res = 2 means "location or file not found".
This does not work either!
In fact in all my experiments loc is always non-NIL, and loc.res always equals 0 - "no error".
This makes me suspect that procedures such as StdDialog.GetSubLoc are buggy, as they seem to rely on loc = NIL for missing directories?
Robert
PS - I have just remembered that I solved this problem (years ago).
Call PathFileExistsW from shlwapi.dll:
Code: Select all
MODULE CasketShlwapiDll ["shlwapi.dll"];
IMPORT SYSTEM, Win := WinApi;
PROCEDURE PathFileExistsW* (path : Win.PtrWSTR) : Win.BOOL;
END CasketShlwapiDll.
with wrapper
Code: Select all
PROCEDURE PathExists* (path : ARRAY OF CHAR) : BOOLEAN;
VAR
k, m : INTEGER;
chr : CHAR;
BEGIN
k := 0; m := -1;
REPEAT
chr := path [k];
IF (chr = '/') OR (chr = '\') THEN m := k END;
INC (k);
UNTIL chr = 0X;
path [m] := 0X;
RETURN Shlwapi.PathFileExistsW (path) = WinApi.TRUE
END PathExists;
Re: File handling
Posted: Fri Nov 20, 2015 8:52 am
by manumart1
You need to test the existence of a folder.
If you know that that folder will ALWAYS have a known file, then you can test for the existence of that file. If file does not exist, then folder does not exist.
For example, the file can be readme.txt, and have a content like this:
This file must be named "readme.txt" and must be in folder "C:\abc\def".
It is necessary for the proper functioning of the application.
Code: Select all
VAR fLoc: Files.Locator; f: Files.File;
fLoc := Files.dir.This("C:\abc\def");
f := Files.dir.Old(fLoc, "readme.txt", Files.shared);
IF fLoc.res # 0 THEN
Error. Folder does not exist
ELSE
f.Close();
END;
My answer is just an indirect way of knowing if a folder exists, and need to impose an obligation to the folder: to store a well known file.
Regards
Re: File handling
Posted: Sun Nov 22, 2015 5:28 pm
by Robert
I think there are several problems with the
solution I posted. My latest suggestion is
Code: Select all
MODULE CasketShlwapiDll ["shlwapi.dll"];
IMPORT SYSTEM, Win := WinApi;
PROCEDURE PathIsDirectoryW* (path : Win.PtrWSTR) : Win.BOOL;
END CasketShlwapiDll.
with a 'wrapper'
Code: Select all
PROCEDURE TrimTail (VAR path : ARRAY OF CHAR);
VAR
k, m : INTEGER;
chr : CHAR;
BEGIN
k := 0; m := -1;
REPEAT
chr := path [k];
IF (chr = '/') OR (chr = '\') THEN m := k END;
INC (k)
UNTIL chr = 0X;
path [m + 1] := 0X
END TrimTail;
PROCEDURE IsDirectory* (path : ARRAY OF CHAR; trimTail : BOOLEAN) : BOOLEAN;
BEGIN
IF trimTail THEN TrimTail (path) END;
RETURN Shlwapi.PathIsDirectoryW (path) # WinApi.FALSE
END IsDirectory;
The option trimTail allows you to pass a full filename, and it will ignore the file part of the full path by cutting out anything after the last '/' or '\'.
This kind of file manipulation seems to be very difficult in BlackBox, but I seem to remember it was always difficult in every language I have ever used!
Cheers,
Robert
Re: File handling
Posted: Mon Nov 23, 2015 11:09 am
by manumart1
Your procedure
TrimTrail is similar to
HostFiles.GetPath, that is not exported.
Code: Select all
MODULE HostFiles;
...
PROCEDURE GetPath (IN fname: FullName; OUT path: FullName);
VAR i: INTEGER;
BEGIN
path := fname$; i := LEN(path$);
WHILE (i > 0) & (path[i] # "\") & (path[i] # "/") & (path[i-1] # ":") DO DEC(i) END;
path[i] := 0X
END GetPath;
Re: File handling
Posted: Wed Nov 25, 2015 3:00 pm
by Josef Templ
It may make sense indeed to add two functions "IsFile" and "IsDir" to Files.Locator.
They would return TRUE if and only if the locator exists and represents a file resp. a directory.
Similar functions are also available in Java, for example.
- Josef
Re: File handling
Posted: Wed Nov 25, 2015 7:31 pm
by Robert
Josef Templ wrote:It may make sense indeed to add two functions ...
I have a list of 5 that I think are of general utility and I find difficult in standard BlackBox.
Whether they should be associated with Locators, or Module Files, or a non-standard BlackBox library in Cpc for example is a different discussion.
Their interfaces are
Code: Select all
PROCEDURE CopyFile (IN srcName, dstName: ARRAY OF CHAR; buildPath, allowOverwrite: BOOLEAN): BOOLEAN;
PROCEDURE CreateDirectory (IN path: ARRAY OF CHAR): BOOLEAN;
PROCEDURE CreatePath (IN path: ARRAY OF CHAR; trimTail: BOOLEAN; OUT cnt: INTEGER);
PROCEDURE IsDirectory (path: ARRAY OF CHAR; trimTail: BOOLEAN): BOOLEAN;
PROCEDURE PathFileExists (name: ARRAY OF CHAR; trimTail: BOOLEAN): BOOLEAN;
If anyone is interested I can send them the full Docu & Mod files.
Regards
Robert