Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2019-10

Multi-platform console application, how to handle file paths?

16 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

I am writing a console application intended to be portable between Windows and Linux and it uses files on the file system for configuration and also for processing data.

Since the path delimiter is different on Unix and Windows I believe I have to handle this in my code, but how?

I could create all paths inside the application using Windows delimiters and then upon usage send them to a "platform filter" like FixPlatformPath() below, which returns the string with the proper delimiters for the platform.
Or else I have to check wherever the paths are dealt with and put conditionals inside the code in many places.
Either way it feels a bit convoluted.

Is there a better way?

function FixPlatformPath(PathIn: string): string;
begin
  {$ifdef UNIX}
    Result:= StringReplace(PathIn, '\', PathDelim, [rfReplaceAll]);
  {$else}
    Result:= StringReplace(PathIn, '/', PathDelim, [rfReplaceAll]);
  {$endif}
end;

This would apply to all functions where files are handled such as reading config data, creating data files or reading data files etc...

Bo Berglund Developer in Sweden

Reply by email

Carlos E. R.
to Bo Berglund

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Bo Berglund wrote 6 lines
I am writing a console application intended to be portable between Windows and Linux and it uses files on the file system for configuration and also for processing data. Since the path delimiter is different on Unix and Windows I believe I have to handle this in my code, but how?

Thinking...

Define a something case {what system} array of strings. Depending on the system detected, you use one or the other array of (constant?) strings, that contains the paths. Assuming they are fixed.

- --
Cheers / Saludos,

Carlos E. R.
(from 15.1 x86_64 at Telcontar)
-----BEGIN PGP SIGNATURE-----

iF0EARECAB0WIQQZEb51mJKK1KpcU/W1MxgcbY1H1QUCXbgi9AAKCRC1MxgcbY1H 1dj2AJ9Qoqusdw0jaoFvLDSmiblv1bhjVQCfccLWxQ0mQO926h0mtAcS4tSADUk= =/Ojl
-----END PGP SIGNATURE-----

Reply by email

Mehmet Erol Sanliturk
to Bo Berglund: I am writing a console application intended to be portable between Windows and Linux and…

In Windows XP , it is possible to use "/" instead of "\" . Therefore , it is NOT necessary to make two different file path representations . I am not using any Windows now , therefore I can not say anything about last Windows versions .

It is very easy to check whether "/" is usable on your Windows : Use a file path with "/" . My opinion is that it will find the related file assuming that your file path is correct other than "/" .

Mehmet Erol Sanliturk

On Tue, Oct 29, 2019 at 2:25 PM Bo Berglund via lazarus <

Show quoted text 42 lines
wrote: I am writing a console application intended to be portable between Windows and Linux and it uses files on the file system for configuration and also for processing data. Since the path delimiter is different on Unix and Windows I believe I have to handle this in my code, but how? I could create all paths inside the application using Windows delimiters and then upon usage send them to a "platform filter" like FixPlatformPath() below, which returns the string with the proper delimiters for the platform. Or else I have to check wherever the paths are dealt with and put conditionals inside the code in many places. Either way it feels a bit convoluted. Is there a better way? function FixPlatformPath(PathIn: string): string; begin {$ifdef UNIX} Result:= StringReplace(PathIn, '\', PathDelim, [rfReplaceAll]); {$else} Result:= StringReplace(PathIn, '/', PathDelim, [rfReplaceAll]); {$endif} end; This would apply to all functions where files are handled such as reading config data, creating data files or reading data files etc... -- Bo Berglund Developer in Sweden -- _______________________________________________ lazarus mailing list https://lists.lazarus-ide.org/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20191029/a5c9bc78/attachment.html>

Reply by email

Michael Van Canneyt
to Bo Berglund: I am writing a console application intended to be portable between Windows and Linux and…
Bo Berglund wrote 28 lines
I am writing a console application intended to be portable between Windows and Linux and it uses files on the file system for configuration and also for processing data. Since the path delimiter is different on Unix and Windows I believe I have to handle this in my code, but how? I could create all paths inside the application using Windows delimiters and then upon usage send them to a "platform filter" like FixPlatformPath() below, which returns the string with the proper delimiters for the platform. Or else I have to check wherever the paths are dealt with and put conditionals inside the code in many places. Either way it feels a bit convoluted. Is there a better way? function FixPlatformPath(PathIn: string): string; begin {$ifdef UNIX} Result:= StringReplace(PathIn, '\', PathDelim, [rfReplaceAll]); {$else} Result:= StringReplace(PathIn, '/', PathDelim, [rfReplaceAll]); {$endif} end; This would apply to all functions where files are handled such as reading config data, creating data files or reading data files etc...

1. Don't hardcode '/' or '\', use the PathDelim constant instead. You will not need any ifdefs.

2. FPC does not care whether you use '\' or '/', and windows normally will accept '/' as well.

3. your "fixplatformpath' exists in FPC, in 2 forms:

https://www.freepascal.org/docs-html/current/rtl/sysutils/dodirseparators.html https://www.freepascal.org/docs-html/current/rtl/sysutils/setdirseparators.html

There are many routines that handle all this transparently:

https://www.freepascal.org/docs-html/current/rtl/sysutils/filenameroutines.html

Michael.

Reply by email

Bo Berglund
to Mehmet Erol Sanliturk: In Windows XP , it is possible to use "/" instead of "\" . Therefore , it is NOT…
Mehmet Erol Sanliturk wrote 9 lines
In Windows XP , it is possible to use "/" instead of "\" . Therefore , it is NOT necessary to make two different file path representations . I am not using any Windows now , therefore I can not say anything about last Windows versions . It is very easy to check whether "/" is usable on your Windows : Use a file path with "/" . My opinion is that it will find the related file assuming that your file path is correct other than "/" .

OK, did not know this.
Now tested on Windows 7 via Windows Explorer and the command line. Both work fine...
So I will use forward slashes in all paths from now on.

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Michael Van Canneyt: 1. Don't hardcode '/' or '\', use the PathDelim constant instead. You will not need any…
Michael Van Canneyt wrote
1. Don't hardcode '/' or '\', use the PathDelim constant instead. You will not need any ifdefs.

The whole thing is that paths might be read from config or other data files and so they will come in either with / or \. I cannot use PathDelim in the target spec because that would not find the erroneous delimiters.

That said, both you and Mehmet pointed out that Windows accepts both delimiters, which I did not know. I have been around too long so I remember the old days...

Anyway, given that the delimiters do not matter I will just code for Linux (the main platform) and not bother with the Windows case.

Thanks for your information!

Bo Berglund Developer in Sweden

Reply by email

Michael Van Canneyt
to Bo Berglund
Bo Berglund wrote 10 lines
On Tue, 29 Oct 2019 12:43:51 +0100 (CET), Michael Van Canneyt via lazarus wrote: > 1. Don't hardcode '/' or '\', use the PathDelim constant instead. > You will not need any ifdefs. The whole thing is that paths might be read from config or other data files and so they will come in either with / or \. I cannot use PathDelim in the target spec because that would not find the erroneous delimiters.

Hence the setdirseparators call. As soon as you read a path from a file, correct it with SetDirSeparators. For the rest you use PathDelim and all will be well.

You're not the only one to have to deal with this, we've all been there :-)

Michael.

Reply by email

Graeme Geldenhuys
to Bo Berglund: On Tue, 29 Oct 2019 12:43:51 +0100 (CET), Michael Van Canneyt via The whole thing is that…
Bo Berglund wrote
I have been around too long so I remember the old days...

Same. Windows should get with the times and switch to Unix. ;-)

On a side note:
After all, Windows still start the drive letters with C: and considering that no PC is the last decade or two has shipped with floppy drives, maybe they could start from A: instead. Most of the people I work with have NO idea why Windows starts with C: as the boot drive instead of A: :-P

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Marco van de Voort
to Graeme Geldenhuys

Op 2019-10-29 om 21:08 schreef Graeme Geldenhuys via lazarus:

Show quoted text 5 lines
On 29/10/2019 12:07 pm, Bo Berglund via lazarus wrote: > I have been around too long so I > remember the old days... Most of the people I work with have NO idea why Windows starts with C: as the boot drive instead of A: :-P

I'm already happy if they can distinguish actual drive files from "most recent used" style virtual folders.:-)

Reply by email

Michael Thompson
to Graeme Geldenhuys: Same. Windows should get with the times and switch to Unix. ;-) On a side note: After…
maybe they could start from A:

Noooo :-) I work offshore for a variety of clients, and using their PCs.

I always ensure my USB key mount at B: (so I don't have to tweak paths in my fpc and Lazarus installs),
I code in an encrypted folder that I mount at A: (using Veracrypt).

The encrypted drive also holds both GIT and SVN repositories.

Been doing this for 10 years now, no conflict on any client PC anywhere :-) I like those holes in A: and B: It's so convenient that my system at home is the same.

Cheers

Mike
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20191030/1acd337f/attachment.html>

Reply by email

DougC
to Michael Thompson

For me A: is  always my archives and B: is my regular backup. Easy to remember!

---- On Tue, 29 Oct 2019 17:16:56 -0400 Michael Thompson via lazarus <mailto:> wrote ----

maybe they could start from A:

Noooo :-)     I work offshore for a variety of clients, and using their PCs. 

I always ensure my USB key mount at B: (so I don't have to tweak paths in my fpc and Lazarus installs),

I code in an encrypted folder that I mount at A: (using Veracrypt). -------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20191029/e65356c6/attachment.html>

Reply by email

Sven Barth
to Graeme Geldenhuys: Same. Windows should get with the times and switch to Unix. ;-) On a side note: After…

Graeme Geldenhuys via lazarus schrieb am
Di., 29. Okt. 2019, 21:08:

Show quoted text 12 lines
On 29/10/2019 12:07 pm, Bo Berglund via lazarus wrote: > I have been around too long so I > remember the old days... Same. Windows should get with the times and switch to Unix. ;-) On a side note: After all, Windows still start the drive letters with C: and considering that no PC is the last decade or two has shipped with floppy drives, maybe they could start from A: instead. Most of the people I work with have NO idea why Windows starts with C: as the boot drive instead of A: :-P

There is still enough software out there that assumes A: and B: are floppy drives and thus either ignores them or handles them especially (I fixed such a relic in our own software just two weeks ago, because a customer had his optical drives as A: and B:, otherwise we wouldn't have noticed that... ).

Regards,
Sven

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20191029/c4636a78/attachment-0001.html>

Reply by email

Mattias Gaertner
to Bo Berglund: On Tue, 29 Oct 2019 12:43:51 +0100 (CET), Michael Van Canneyt via The whole thing is that…
[...] Anyway, given that the delimiters do not matter I will just code for Linux (the main platform) and not bother with the Windows case.

There are some differences. For example filenames are case insensitive.
FileExists returns false under Windows for directories. Windows allows empty names, so these are different things: 'C:\a', 'C:\a\', 'C:\a\\'.
Windows has one current directory per partition.
Windows knows specials paths starting with '\\'.
etc.

Mattias

Reply by email

Bo Berglund
to Mattias Gaertner
Mattias Gaertner wrote
Windows knows specials paths starting with '\\'.

But I don't! :(
What is special with these? I have noted tghat if I spell a path wrong (copy paste or oterwise) and get two \\ instead of one it still works fine. But maybe there is some special meaning too?

Anyway, I ran the program test on Windows now using the suggested function:
FindAllFiles(FileList, TaskDir, '*.conf', false);
FileList shows the full path to the files but excluding the drive letter, which is not part of the "TaskDir" variable. It checked the dir in the current drive (where the exe file is located).

Bo Berglund Developer in Sweden

Reply by email

Bart
to Bo Berglund
AM Bo Berglund wrote
>Windows knows specials paths starting with '\\'. But I don't! :( What is special with these?

\\?\C:\foo\bar\..\..
is not the same path as
C:\foo\bar\..\.. (which basically is C:\)

If a path starts with \\?\ like above, all characters in the path are taken literally (so you cannot construct a relative path), or ot is used to build a UNC path: \\?\UNC\
IIRC then also device names start with \\.\ or something the like.

See https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file

Bart

Bart

Reply by email