I am trying to add image files into a library, and as part of that, to optionally copy or move & rename them to give them 8.3 file names. How should I go separating the file extension from the name in order to attach it to a fresh file name?
If you have Capesoft’s String Theory it has a simple method for splitting file names:
https://www.capesoft.com/docs/StringTheory3/StringTheory.htm#ExtensionOnly
Otherwise you can use the FnSplit API call:
http://computer-programming-forum.com/18-clarion/04339ac246d4cd98.htm
You can use PathSplit function from CWUtil.INC, or just find last dot position in a filename:
LastDotPos = INSTRING('.', FileName, -1, SIZE(FileName))
In addition to the other responses, if you are truly going for an 8.3 filename, you might need to do extra stuff if your extension is longer than 3 characters.
Also, some systems could have 8.3 disabled. Google 8dot3name.
What value of the extension is being returned for the filename X:\Tests.1\nothing ?
Do you mean " What value of the last dot position is being returned for the filename X:\Tests.1\nothing ?"?
Actually good point, it needs to keep in mind that there could be files with no extension.
StringTheory handles this. I have seen it in the StrngTheoy source a few days back.
Good Point I should think of when I have a full name to first cutoff after last backslash:
LastBSPos = INSTRING('\', PathAndFile, -1, SIZE(PathAndFile)) !End of Path at last "\"
FileName = SUB(PathAndFile, LastBSPos+1, 255) !Take after x:\path\ FILENAME.EXT
LastDotPos = INSTRING('.', FileName, -1, SIZE(FileName))
FileExten = SUB(FileName, LastDotPos+1, 255)
What’s about the filename X:nothing
?
What’s about the directory name X:\Level.1\Level.2\Level.3\..
?
Exten would be blank which I think is correct
I would typically know if I had a Directory Name only instead of a File Name.
Calling the File Dialog with File:Directory can only return a File Name … But often there is also an ENTRY() for a File Name so it is possible a User could paste into that a Path like C:\MyDocs\Archive.PDF\June2023
that would confuse that Extension code.
Unfortunately the Clarion Exists() will not indicate File or Path, I have required that a few times. Code like this can be used:
MAP
ExistsFileOrPath(STRING FileOrPathName,<*LONG OutAttributes>),BYTE !Return 1=File 2=Path 0=N/A
MODULE('Win32')
GetFileAttributes(*CSTRING FileName),LONG,PASCAL,RAW,DLL(1),NAME('GetFileAttributesA')
END
END
ExistsFileOrPath PROCEDURE(STRING FN, <*LONG OutAttr>)!,BYTE !1=File 2=Path
cName CSTRING(261),AUTO
Attr LONG,AUTO
ForP12 BYTE
!_INVALID_FILE_ATTRIBUTES EQUATE(-1) !If function fails it returns INVALID_FILE_ATTRIBUTES. Call GetLastError() for error information,
!_FILE_ATTRIBUTE_DIRECTORY EQUATE(10h) !The handle that identifies a directory
CODE
cName=CLIP(FN)
Attr = GetFileAttributes(cName)
IF ~OMITTED(OutAttr) THEN OutAttr=Attr.
IF Attr <> -1 THEN ForP12=CHOOSE(~BAND(Attr,10h),1,2).
RETURN ForP12
I see that this function PathSplit is a rename of fnsplit. I used the fnsplit from clib.clw in some of my classes. The clib.clw is from 1995 though, so I wonder if it is present in newer Clarion releases?
fnsplit has been there forever, and still remains.
The goofy thing is the FN Split in CwUtil is just the C version declared in the CwUtil.INC file with a better name PathSplit
than NAME('_fnsplit')
.
!-- CwUtil.INC in LibSrc ---
MODULE('Core')
PathSplit(CONST *CSTRING path, <*CSTRING drive>, <*CSTRING dir>, <*CSTRING file>, <*CSTRING ext>), SIGNED, PROC, RAW, NAME('_fnsplit')
PathMerge(*CSTRING path, <*CSTRING drive>, <*CSTRING dir>, <*CSTRING file>, <*CSTRING ext>), SIGNED, PROC, RAW, NAME('_fnmerge')
END
So you have to define all CSTRING variables to call it. IMO the purpose of CwUtil is to make wrapper functions so its easy to call API/RTL functions with normal Clarion types like STRING. Its not like it was hard to do
Not disagreeing. I always just used my own wrapper func.