Delphi : how to recurse down paths over 255 characters and read file attributes
I am writing a console app and need to traverse a directory structure with paths much greater than 255 characters and then read attributes of the files within them.
Historically, I used recursion and FindFirst using Turbo Delphi from 2006 but this seems to skip over paths greater than 255 characters.
Can I swap out the FindFirst() function for something else? or do I have to take a different approach?
If you prefix file names with \\?\
then you enable extended-length path parsing and so escape from the 260 character path length limit.
In order for this prefix to work you need to be calling the Unicode versions of the Win32 API functions. So if you were using a Unicode Delphi then this is all you need to do. But since you are using a pre-Unicode Delphi you'll have to roll your own version of FindFirst
that calls Unicode versions of the API functions. You'll be calling FindFirstFileW
, FindNextFileW
, FindClose
and using the Unicode version of the struct, WIN32_FIND_DATAW
.
These issues are discussed in great length over on MSDN: Naming Files, Paths, and Namespaces.
In your particular scenario, the documentation for FindFirstFileW
calls the issue out like this:
In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" to the path.
Note that the two file name fields in WIN32_FIND_DATAW
are limited in length to 260 characters. That is fine because they only contain the relative part of the name, that is the object name relative to the containing directory. You only need to use the \\?\
prefix when you call FindFirstFileW
.
In order to use the Unicode version of this API you'll use a WideString
for the lpFileName
parameter of FindFirstFileW
and pass it using PWideChar(FileName)
.
var
FileName: WideString;
....
// initialise FileName, this will happen in your recursion
FindHandle := FindFirstFileW(PWideChar(FileName), FindData);
As for the file attributes, they can be read out of the WIN32_FIND_DATAW
struct on each iteration. That part of your code need not change. The only thing you need to fix is to get the >260 char parsing on the initial call to FindFirstFileW
. Everything else flows on quite normally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With