Opening file paths with spaces in Delphi 5
(Using Delphi 5)
I am trying to open a log file using the following code:
// The result of this is:
// C:\Program Files\MyProgram\whatever\..\Blah\logs\mylog.log
fileName := ExtractFilePath(Application.ExeName) + '..\Blah\logs\mylog.log';
// The file exists check passes
if (FileExists(fileName)) then
begin
logs := TStringList.Create();
// An exception is thrown here: 'unable to open file'
logs.LoadFromFile(fileName);
end;
If I move the log file to C: \ mylog.log the code works fine. I think the spaces in the file path are confusing. Does anyone know if this is ok for Delphi 5? If so, is there a function to escape the space or convert the path to a Windows 8.3 path?
a source to share
I'm sure Delphi 5 handles spaces in file names, but it's been a very long time since I used this particular version. Is the file open by another process? It can also be a permissions issue. Can you, instead of loading it into a tStringList, try opening it with tFileStream with the file set to "fmOpenRead or fmShareDenyNone".
fStm := tFileStream.Create( filename, fmOpenRead or fmShareDenyNone );
then load your tStringlist from stream:
Logs.LoadFromStream ( fStm );
a source to share
Are you sure it's not the ".." that is causing the problem, not spaces. Have you tried to see if it works for
c:\My\Path\nospaces\
If so and you always use the .. \ path, perhaps write a simple function to remove the last folder from your program path and create the full correct path.
a source to share
It's weird that Delphi 5 would be wrong about this. I am aware of the problem with the FileExists error in files with an invalid last modified date (since it uses FileAge internally), but the opposite is true here. Instead of using "..", I would risk using the current path and load from a relative path: LoadFromFile('..\Something\Something.log');
especially for small applications, or call ExtractFilePath twice:ExtractFilePath(ExtractFilePath(Application.ExeName))
a source to share
I'm pretty sure Delphi has always handled spaces, so I doubt this is the problem.
You are not showing the full path. Is there a chance it's really long? For example, I could believe the problem with paths longer than 255 characters.
It is also a bad idea to put the log files in Program Files. Often, regular users are not allowed to write anything in the Program Files section.
a source to share
Spaces are not a problem. While this '..'
may be a problem in Delphi 5, most likely the file is locked by the process that is writing to it. If you are in control of it, make sure it opens the file with fmShareDenyWrite
, not fmShareExclusive
or fmShareCompat
(which is the default).
Alternatively, you can use:
fileName := ExpandFileName(ExtractFilePath(Application.ExeName) + '..\Blah\logs\mylog.log');
to get the absolute path from the relative path.
Also, as others have said, it's a good idea to write something in Program Files. Regular users (not "Administrators" or "Owners") do not have write permissions there (although it will be virtualized in Vista, still not a good idea). Use the appropriate application data folder for the user (or all users). This folder can be obtained with:
SHGetFolderPath(0,folder,0,SHGFP_TYPE_CURRENT,@path[0])
where folder
either CSIDL_COMMON_APPDATA
, or CSIDL_LOCAL_APPDATA
. See this delphi.about.com article for an example.
a source to share
Plain:
// if log file = "C:\Program files\mylog.log"
// you'll get :
// »»»»» fileName = 'C:\Program files..\Blah\logs\mylog.log'
// if log file = "C:\mylog.log"
// you'll get :
// »»»»» fileName = 'C:..\Blah\logs\mylog.log'
Try this code, I'm sure it will suit your needs:
fileName := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) + '..\Blah\logs\mylog.log';
Hello,
Russian salad
a source to share