Search code examples
delphivalidationfilenamessanitization

How can I sanitize a string for use as a filename?


I've got a routine that converts a file into a different format and saves it. The original datafiles were numbered, but my routine gives the output a filename based on an internal name found in the original.

I tried to batch-run it on a whole directory, and it worked fine until I hit one file whose internal name had a slash in it. Oops! And if it does that here, it could easily do it on other files. Is there an RTL (or WinAPI) routine somewhere that will sanitize a string and remove invalid symbols so it's safe to use as a filename?


Solution

  • You can use PathGetCharType function, PathCleanupSpec function or the following trick:

      function IsValidFilePath(const FileName: String): Boolean;
      var
        S: String;
        I: Integer;
      begin
        Result := False;
        S := FileName;
        repeat
          I := LastDelimiter('\/', S);
          MoveFile(nil, PChar(S));
          if (GetLastError = ERROR_ALREADY_EXISTS) or
             (
               (GetFileAttributes(PChar(Copy(S, I + 1, MaxInt))) = INVALID_FILE_ATTRIBUTES)
               and
               (GetLastError=ERROR_INVALID_NAME)
             ) then
            Exit;
          if I>0 then
            S := Copy(S,1,I-1);
        until I = 0;
        Result := True;
      end;
    

    This code divides string into parts and uses MoveFile to verify each part. MoveFile will fail for invalid characters or reserved file names (like 'COM') and return success or ERROR_ALREADY_EXISTS for valid file name.


    PathCleanupSpec is in the Jedi Windows API under Win32API/JwaShlObj.pas