How to construct a multi-part file reference

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

How to construct a multi-part file reference

jfabry
Hi all,

I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.

For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’

And the bingo question is: what do I do if I both strings use different kinds of separators?

TIA,

---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

Udo Schneider
Hi Johan,

I remember running into similar problems because I didn't understand the
FileSystem philosophy ... and dealing with strings and concatenating
them is so much easier, right? :-)

After reading the chapter on FileSystem several times over and over
again the IMHO most important part of it to get the grasp of FileSystem
is on page 13
(http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/FileSystem.pdf):

"
FileReference = FileSystem + Path
Paths and filesystems are the lowest level of the FileSystem API. A
FileReference combines a path and a filesystem into a single object
which provides a simpler protocol for working with files as we show in
the previous section. References implement the path protocol with
methods like /, parent and resolve:.
"

So in your example ‘/home/jfabry’ and ‘test/code/foo.txt’ are just
(relative) path strings. They do not reference anything outside of the
context of a filesystem. The hard part for me to understand was the fact
that a path may not be unique. The same path might reference different
files in different filesystems.
This is especially strange coming from a *nix background where there is
only one filesystem.
But even on Windows one could argue that the OS nowadays only knows one
filesystem: You can reference any file via a UNC path ... drives,
shares, partitions, URIs and other filesystems are simply aliases into
the UNC space.
The nice thing of the FileSystem API is it's ability to transparently
use files in-Memory, archives, FTP, WebDav, S3 ... . All from within
Pharo with the same consistent API. E.g. if you have the
FileSystemNetwork
(http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork) installed
you can do something like:



"Obtain a FTP FileSystem"
fs := FileSystem ftp: 'ftp://ftp.2600.com'.

"Get working directory"
wd := fs workingDirectory .

"Print the following expression!"
(wd /  'pub' / 'publications' / 'n0way') children.
(wd /  'pub' / 'publications' / 'n0way' / 'README') contents.

"Open a FileList on the FileSystem"
FileList openOn: wd.

"Remember to close if you are finished!"
fs close.




So to make a long story short: Both your strings contain paths. So we
have to convert them into Paths and somehow combine them with a
FileSystem to get a valid FileReference:



"I changed the second string to demonstrate dealing with different
delimiters"
dirString := '/home/jfabry'.
fileString := 'test\code\foo.txt'.

"Convert path strings to Paths"
dirPath := Path from: dirString delimiter: $/.
filePath := Path from: fileString delimiter: $\.
"Please note the Paths do not reference anything. We have no FileSystem
context yet"

"The FileSystem our Paths will be resolved within"
diskFs := FileSystem disk.

"FileReference for the root directory in the FS"
rootRef := diskFs root.

"Resolve our Paths in the Context of the Reference"
dirRef := rootRef resolve: dirPath.
fileRef := dirRef resolve: filePath. "File @ /home/jfabry/test/code/foo.txt"

"Please note the fileRef printString. 'File' denotes the FileSystem -
not the fact that this is a file! Then you have the path after the at sign"





I hope this helps.

Final advice: In Pharo you should *never never never* assume that a Path
is "enough" to reference a file. You will always need the context (it's
FileSystem) as well. And that's exactly what a FileReference (see above)
is. So if you only have a Path it's questionable to assume that you can
simply combine it with a DiskFileSystem to get a valid reference. What
if the Path references a file in a ZIP in-Memory archive? Trying to
access the Path on disk will yield no result. So always always always
store/pass a FileReference if possible!!!!
I did run into that issue in the past with archive/net FileSystems where
some dev tools at one point extracted the Path from the FileReference
and passed them arround. Down the stack some other methods needed the
file contents. Because only the Path was passed they assumed they could
retrieve the contents by simply combining it with a DiskFileSystem ...
and boom!


CU,

Udo


On 07/05/16 00:33, Johan Fabry wrote:

> Hi all,
>
> I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.
>
> For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’
>
> And the bingo question is: what do I do if I both strings use different kinds of separators?
>
> TIA,
>
> ---> Save our in-boxes! http://emailcharter.org <---
>
> Johan Fabry   -   http://pleiad.cl/~jfabry
> PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

Sven Van Caekenberghe-2
Hi Udo,

That is a very good explanation, thank you.

I always had the impression that Path is not meant for public use, just part of the implementation. Should it not be part of the -Public package then ?

Maybe there are still other ways to parse a Windows path while running on a Mac or Linux ?

Sven

> On 07 May 2016, at 10:46, Udo Schneider <[hidden email]> wrote:
>
> Hi Johan,
>
> I remember running into similar problems because I didn't understand the FileSystem philosophy ... and dealing with strings and concatenating them is so much easier, right? :-)
>
> After reading the chapter on FileSystem several times over and over again the IMHO most important part of it to get the grasp of FileSystem is on page 13 (http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/FileSystem.pdf):
>
> "
> FileReference = FileSystem + Path
> Paths and filesystems are the lowest level of the FileSystem API. A FileReference combines a path and a filesystem into a single object which provides a simpler protocol for working with files as we show in the previous section. References implement the path protocol with methods like /, parent and resolve:.
> "
>
> So in your example ‘/home/jfabry’ and ‘test/code/foo.txt’ are just (relative) path strings. They do not reference anything outside of the context of a filesystem. The hard part for me to understand was the fact that a path may not be unique. The same path might reference different files in different filesystems.
> This is especially strange coming from a *nix background where there is only one filesystem.
> But even on Windows one could argue that the OS nowadays only knows one filesystem: You can reference any file via a UNC path ... drives, shares, partitions, URIs and other filesystems are simply aliases into the UNC space.
> The nice thing of the FileSystem API is it's ability to transparently use files in-Memory, archives, FTP, WebDav, S3 ... . All from within Pharo with the same consistent API. E.g. if you have the FileSystemNetwork (http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork) installed you can do something like:
>
>
>
> "Obtain a FTP FileSystem"
> fs := FileSystem ftp: 'ftp://ftp.2600.com'.
>
> "Get working directory"
> wd := fs workingDirectory .
>
> "Print the following expression!"
> (wd /  'pub' / 'publications' / 'n0way') children.
> (wd /  'pub' / 'publications' / 'n0way' / 'README') contents.
>
> "Open a FileList on the FileSystem"
> FileList openOn: wd.
>
> "Remember to close if you are finished!"
> fs close.
>
>
>
>
> So to make a long story short: Both your strings contain paths. So we have to convert them into Paths and somehow combine them with a FileSystem to get a valid FileReference:
>
>
>
> "I changed the second string to demonstrate dealing with different delimiters"
> dirString := '/home/jfabry'.
> fileString := 'test\code\foo.txt'.
>
> "Convert path strings to Paths"
> dirPath := Path from: dirString delimiter: $/.
> filePath := Path from: fileString delimiter: $\.
> "Please note the Paths do not reference anything. We have no FileSystem context yet"
>
> "The FileSystem our Paths will be resolved within"
> diskFs := FileSystem disk.
>
> "FileReference for the root directory in the FS"
> rootRef := diskFs root.
>
> "Resolve our Paths in the Context of the Reference"
> dirRef := rootRef resolve: dirPath.
> fileRef := dirRef resolve: filePath. "File @ /home/jfabry/test/code/foo.txt"
>
> "Please note the fileRef printString. 'File' denotes the FileSystem - not the fact that this is a file! Then you have the path after the at sign"
>
>
>
>
>
> I hope this helps.
>
> Final advice: In Pharo you should *never never never* assume that a Path is "enough" to reference a file. You will always need the context (it's FileSystem) as well. And that's exactly what a FileReference (see above) is. So if you only have a Path it's questionable to assume that you can simply combine it with a DiskFileSystem to get a valid reference. What if the Path references a file in a ZIP in-Memory archive? Trying to access the Path on disk will yield no result. So always always always store/pass a FileReference if possible!!!!
> I did run into that issue in the past with archive/net FileSystems where some dev tools at one point extracted the Path from the FileReference and passed them arround. Down the stack some other methods needed the file contents. Because only the Path was passed they assumed they could retrieve the contents by simply combining it with a DiskFileSystem ... and boom!
>
>
> CU,
>
> Udo
>
>
> On 07/05/16 00:33, Johan Fabry wrote:
>> Hi all,
>>
>> I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.
>>
>> For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’
>>
>> And the bingo question is: what do I do if I both strings use different kinds of separators?
>>
>> TIA,
>>
>> ---> Save our in-boxes! http://emailcharter.org <---
>>
>> Johan Fabry   -   http://pleiad.cl/~jfabry
>> PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile
>>
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

Udo Schneider
Hi Sven,

 > I always had the impression that Path is not meant for public use,
 > just part of the implementation. Should it not be part of the -Public
 > package then ?
I'm a bit schizophrenic on this one :-)

My "first self" argues that Path as a part of the FileSystem API should
indeed remain/be private. Especially because most of us still thing of
paths as strings. And manipulating them detached from a filesystem poses
some risks (mentioned below). In addition the class comment (IMHO
rightly) states: "I'm a private and abstract filesystem path,
independent of the string representation used to describe paths on a
specific filesystem".

My "second self" argues that a Path could denote so much more than an
identifier in filesystem space. Just think of a navigation path in
websites (breadcrumbs). In this context Path would be a generalized way
to deal of structuring an abstract space by mean of string identifiers.
And a "FileSystemPath" would be a (private - see above) subclass adding
the filesystem behavior (like detecting absolute filesystem paths).

 > Maybe there are still other ways to parse a Windows path while
 > running on a Mac or Linux ?
I'm not sure I'm getting this one.

Path works the same on all platforms. You might just have to manually
specify a delimiter if you want to parse a string. This IMHO is a good
thing - you should know the format of strings you're getting :-)
I've seen code like this:

"Path Splitting for Windows and *nix"
pathParts := pathString substrings: '/\'.

This works /most/ of the time. It just fails when considering that e.g.
"\" is a valid character in *nix filenames ...

'/home/udos/Hello\World' substrings: '/\'.  "#('home' 'udos' 'Hello'
'World')"

but

"Not specifying delimiter here - $/ is default then"
Path from: '/home/udos/Hello\World'.  "Path / 'home' / 'udos' /
'Hello\World'"

And considering that some platforms use totally different path
delimiters (e.g. ":" on Mac OS, "." on RISC/OS) it's IMHO cleaner to
only split on one Character (like Path>>#from:delimiter:) and assign the
responsibility of knowing which delimiter to use to the programmer.

However ignoring "minor" platforms and issues with delimiters in names
there is no big difference between String>>#substrings: and
Path>>#from:delimiter: at first. But the getting back a Path is IMHO
much more intention revealing than a collection of strings. Especially
because you're getting back an AbsolutePath or RelativePath which is
even more intention revealing and something you may completely miss when
splitting strings.


absoluteArray := '/home/root/file' substrings: '/'.  "#('home' 'root'
'file')"
relativeArray := ('home/root/file' substrings: '/').  "#('home' 'root'
'file')"
"The distinction between absolute and relative is lost here!"

absoluteArray = relativeArray.  "true"
"Both paths may have referenced the same file - but also may not!!!!"

absolutePath := Path from: '/home/root/file' delimiter: $/.  "Path /
'home' / 'root' / 'file'".
absolutePath class.  "AbsolutePath"
relativePath := Path from: 'home/root/file' delimiter: $/.  "Path *
'home' / 'root' / 'file'"
relativePath class. "RelativePath".
"The distinction between absolute and relative paths is kept.
In #printString and class"

absolutePath = relativePath.  "false"
"No danger to confuse absolute and relative paths here"



Or did I get you completely wrong?

CU,

Udo




On 07/05/16 10:57, Sven Van Caekenberghe wrote:

> Hi Udo,
>
> That is a very good explanation, thank you.
>
> I always had the impression that Path is not meant for public use, just part of the implementation. Should it not be part of the -Public package then ?
>
> Maybe there are still other ways to parse a Windows path while running on a Mac or Linux ?
>
> Sven
>
>> On 07 May 2016, at 10:46, Udo Schneider <[hidden email]> wrote:
>>
>> Hi Johan,
>>
>> I remember running into similar problems because I didn't understand the FileSystem philosophy ... and dealing with strings and concatenating them is so much easier, right? :-)
>>
>> After reading the chapter on FileSystem several times over and over again the IMHO most important part of it to get the grasp of FileSystem is on page 13 (http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/FileSystem.pdf):
>>
>> "
>> FileReference = FileSystem + Path
>> Paths and filesystems are the lowest level of the FileSystem API. A FileReference combines a path and a filesystem into a single object which provides a simpler protocol for working with files as we show in the previous section. References implement the path protocol with methods like /, parent and resolve:.
>> "
>>
>> So in your example ‘/home/jfabry’ and ‘test/code/foo.txt’ are just (relative) path strings. They do not reference anything outside of the context of a filesystem. The hard part for me to understand was the fact that a path may not be unique. The same path might reference different files in different filesystems.
>> This is especially strange coming from a *nix background where there is only one filesystem.
>> But even on Windows one could argue that the OS nowadays only knows one filesystem: You can reference any file via a UNC path ... drives, shares, partitions, URIs and other filesystems are simply aliases into the UNC space.
>> The nice thing of the FileSystem API is it's ability to transparently use files in-Memory, archives, FTP, WebDav, S3 ... . All from within Pharo with the same consistent API. E.g. if you have the FileSystemNetwork (http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork) installed you can do something like:
>>
>>
>>
>> "Obtain a FTP FileSystem"
>> fs := FileSystem ftp: 'ftp://ftp.2600.com'.
>>
>> "Get working directory"
>> wd := fs workingDirectory .
>>
>> "Print the following expression!"
>> (wd /  'pub' / 'publications' / 'n0way') children.
>> (wd /  'pub' / 'publications' / 'n0way' / 'README') contents.
>>
>> "Open a FileList on the FileSystem"
>> FileList openOn: wd.
>>
>> "Remember to close if you are finished!"
>> fs close.
>>
>>
>>
>>
>> So to make a long story short: Both your strings contain paths. So we have to convert them into Paths and somehow combine them with a FileSystem to get a valid FileReference:
>>
>>
>>
>> "I changed the second string to demonstrate dealing with different delimiters"
>> dirString := '/home/jfabry'.
>> fileString := 'test\code\foo.txt'.
>>
>> "Convert path strings to Paths"
>> dirPath := Path from: dirString delimiter: $/.
>> filePath := Path from: fileString delimiter: $\.
>> "Please note the Paths do not reference anything. We have no FileSystem context yet"
>>
>> "The FileSystem our Paths will be resolved within"
>> diskFs := FileSystem disk.
>>
>> "FileReference for the root directory in the FS"
>> rootRef := diskFs root.
>>
>> "Resolve our Paths in the Context of the Reference"
>> dirRef := rootRef resolve: dirPath.
>> fileRef := dirRef resolve: filePath. "File @ /home/jfabry/test/code/foo.txt"
>>
>> "Please note the fileRef printString. 'File' denotes the FileSystem - not the fact that this is a file! Then you have the path after the at sign"
>>
>>
>>
>>
>>
>> I hope this helps.
>>
>> Final advice: In Pharo you should *never never never* assume that a Path is "enough" to reference a file. You will always need the context (it's FileSystem) as well. And that's exactly what a FileReference (see above) is. So if you only have a Path it's questionable to assume that you can simply combine it with a DiskFileSystem to get a valid reference. What if the Path references a file in a ZIP in-Memory archive? Trying to access the Path on disk will yield no result. So always always always store/pass a FileReference if possible!!!!
>> I did run into that issue in the past with archive/net FileSystems where some dev tools at one point extracted the Path from the FileReference and passed them arround. Down the stack some other methods needed the file contents. Because only the Path was passed they assumed they could retrieve the contents by simply combining it with a DiskFileSystem ... and boom!
>>
>>
>> CU,
>>
>> Udo
>>
>>
>> On 07/05/16 00:33, Johan Fabry wrote:
>>> Hi all,
>>>
>>> I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.
>>>
>>> For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’
>>>
>>> And the bingo question is: what do I do if I both strings use different kinds of separators?
>>>
>>> TIA,
>>>
>>> ---> Save our in-boxes! http://emailcharter.org <---
>>>
>>> Johan Fabry   -   http://pleiad.cl/~jfabry
>>> PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile
>>>
>>>
>>>
>>
>>
>>
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

Nicolai Hess-3-2
In reply to this post by jfabry


2016-05-07 0:33 GMT+02:00 Johan Fabry <[hidden email]>:
Hi all,

I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.

For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’

And the bingo question is: what do I do if I both strings use different kinds of separators?

I  think

‘/home/jfabry’ asFileReference resolve: ‘test/code/foo.txt’

works on both platform, with both separators, no?


 

TIA,

---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile



Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

jfabry
In reply to this post by Udo Schneider
Hi Udo,

that’s a very detailed explanation, thanks for taking the time to write it!

> On May 7, 2016, at 05:46, Udo Schneider <[hidden email]> wrote:
>
> Hi Johan,
>
> I remember running into similar problems because I didn't understand the FileSystem philosophy ... and dealing with strings and concatenating them is so much easier, right? :-)
>
> After reading the chapter on FileSystem several times over and over again the IMHO most important part of it to get the grasp of FileSystem is on page 13 (http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/FileSystem.pdf):
>
> "
> FileReference = FileSystem + Path
> Paths and filesystems are the lowest level of the FileSystem API. A FileReference combines a path and a filesystem into a single object which provides a simpler protocol for working with files as we show in the previous section. References implement the path protocol with methods like /, parent and resolve:.
> "
>
> So in your example ‘/home/jfabry’ and ‘test/code/foo.txt’ are just (relative) path strings. They do not reference anything outside of the context of a filesystem. The hard part for me to understand was the fact that a path may not be unique. The same path might reference different files in different filesystems.
> This is especially strange coming from a *nix background where there is only one filesystem.
> But even on Windows one could argue that the OS nowadays only knows one filesystem: You can reference any file via a UNC path ... drives, shares, partitions, URIs and other filesystems are simply aliases into the UNC space.
> The nice thing of the FileSystem API is it's ability to transparently use files in-Memory, archives, FTP, WebDav, S3 ... . All from within Pharo with the same consistent API. E.g. if you have the FileSystemNetwork (http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork) installed you can do something like:
>
>
>
> "Obtain a FTP FileSystem"
> fs := FileSystem ftp: 'ftp://ftp.2600.com'.
>
> "Get working directory"
> wd := fs workingDirectory .
>
> "Print the following expression!"
> (wd /  'pub' / 'publications' / 'n0way') children.
> (wd /  'pub' / 'publications' / 'n0way' / 'README') contents.
>
> "Open a FileList on the FileSystem"
> FileList openOn: wd.
>
> "Remember to close if you are finished!"
> fs close.
>
>
>
>
> So to make a long story short: Both your strings contain paths. So we have to convert them into Paths and somehow combine them with a FileSystem to get a valid FileReference:
>
>
>
> "I changed the second string to demonstrate dealing with different delimiters"
> dirString := '/home/jfabry'.
> fileString := 'test\code\foo.txt'.
>
> "Convert path strings to Paths"
> dirPath := Path from: dirString delimiter: $/.
> filePath := Path from: fileString delimiter: $\.
> "Please note the Paths do not reference anything. We have no FileSystem context yet"
>
> "The FileSystem our Paths will be resolved within"
> diskFs := FileSystem disk.
>
> "FileReference for the root directory in the FS"
> rootRef := diskFs root.
>
> "Resolve our Paths in the Context of the Reference"
> dirRef := rootRef resolve: dirPath.
> fileRef := dirRef resolve: filePath. "File @ /home/jfabry/test/code/foo.txt"
>
> "Please note the fileRef printString. 'File' denotes the FileSystem - not the fact that this is a file! Then you have the path after the at sign"
>
>
>
>
>
> I hope this helps.
>
> Final advice: In Pharo you should *never never never* assume that a Path is "enough" to reference a file. You will always need the context (it's FileSystem) as well. And that's exactly what a FileReference (see above) is. So if you only have a Path it's questionable to assume that you can simply combine it with a DiskFileSystem to get a valid reference. What if the Path references a file in a ZIP in-Memory archive? Trying to access the Path on disk will yield no result. So always always always store/pass a FileReference if possible!!!!
> I did run into that issue in the past with archive/net FileSystems where some dev tools at one point extracted the Path from the FileReference and passed them arround. Down the stack some other methods needed the file contents. Because only the Path was passed they assumed they could retrieve the contents by simply combining it with a DiskFileSystem ... and boom!
>
>
> CU,
>
> Udo
>
>
> On 07/05/16 00:33, Johan Fabry wrote:
>> Hi all,
>>
>> I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.
>>
>> For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’
>>
>> And the bingo question is: what do I do if I both strings use different kinds of separators?
>>
>> TIA,
>>
>> ---> Save our in-boxes! http://emailcharter.org <---
>>
>> Johan Fabry   -   http://pleiad.cl/~jfabry
>> PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile
>>
>>
>>
>
>
>
>



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

jfabry
In reply to this post by Nicolai Hess-3-2
Hi Nicolai,

I don’t know if it works with both separators, but it’s simple and works on MacOS at least, so that’s good enough for me now. Thanks for pointing it out to me !

On May 8, 2016, at 11:53, Nicolai Hess <[hidden email]> wrote:



2016-05-07 0:33 GMT+02:00 Johan Fabry <[hidden email]>:
Hi all,

I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.

For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’

And the bingo question is: what do I do if I both strings use different kinds of separators?

I  think

‘/home/jfabry’ asFileReference resolve: ‘test/code/foo.txt’

works on both platform, with both separators, no?


 

TIA,

---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile






---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile

Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

Sven Van Caekenberghe-2
In reply to this post by Nicolai Hess-3-2

> On 08 May 2016, at 16:53, Nicolai Hess <[hidden email]> wrote:
>
>
>
> 2016-05-07 0:33 GMT+02:00 Johan Fabry <[hidden email]>:
> Hi all,
>
> I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.
>
> For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’
>
> And the bingo question is: what do I do if I both strings use different kinds of separators?
>
> I  think
>
> ‘/home/jfabry’ asFileReference resolve: ‘test/code/foo.txt’
>
> works on both platform, with both separators, no?

That seems to be the correct way to use the high level API.

> TIA,
>
> ---> Save our in-boxes! http://emailcharter.org <---
>
> Johan Fabry   -   http://pleiad.cl/~jfabry
> PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to construct a multi-part file reference

Sven Van Caekenberghe-2
In reply to this post by Udo Schneider

> On 07 May 2016, at 12:08, Udo Schneider <[hidden email]> wrote:
>
> Hi Sven,
>
> > I always had the impression that Path is not meant for public use,
> > just part of the implementation. Should it not be part of the -Public
> > package then ?
> I'm a bit schizophrenic on this one :-)

The whole FileSystem design is very cool, but sometimes a bit confusing. The first step is of course to fully understand the current design and the ideas behind it. Only then, maybe, we can start to think about what needs to be changed. Right now, I feel I am no ready to do that.

> My "first self" argues that Path as a part of the FileSystem API should indeed remain/be private. Especially because most of us still thing of paths as strings. And manipulating them detached from a filesystem poses some risks (mentioned below). In addition the class comment (IMHO rightly) states: "I'm a private and abstract filesystem path, independent of the string representation used to describe paths on a specific filesystem".
>
> My "second self" argues that a Path could denote so much more than an identifier in filesystem space. Just think of a navigation path in websites (breadcrumbs). In this context Path would be a generalized way to deal of structuring an abstract space by mean of string identifiers. And a "FileSystemPath" would be a (private - see above) subclass adding the filesystem behavior (like detecting absolute filesystem paths).
>
> > Maybe there are still other ways to parse a Windows path while
> > running on a Mac or Linux ?
> I'm not sure I'm getting this one.
>
> Path works the same on all platforms. You might just have to manually specify a delimiter if you want to parse a string. This IMHO is a good thing - you should know the format of strings you're getting :-)
> I've seen code like this:
>
> "Path Splitting for Windows and *nix"
> pathParts := pathString substrings: '/\'.
>
> This works /most/ of the time. It just fails when considering that e.g. "\" is a valid character in *nix filenames ...
>
> '/home/udos/Hello\World' substrings: '/\'.  "#('home' 'udos' 'Hello' 'World')"
>
> but
>
> "Not specifying delimiter here - $/ is default then"
> Path from: '/home/udos/Hello\World'.  "Path / 'home' / 'udos' / 'Hello\World'"
>
> And considering that some platforms use totally different path delimiters (e.g. ":" on Mac OS, "." on RISC/OS) it's IMHO cleaner to only split on one Character (like Path>>#from:delimiter:) and assign the responsibility of knowing which delimiter to use to the programmer.
>
> However ignoring "minor" platforms and issues with delimiters in names there is no big difference between String>>#substrings: and Path>>#from:delimiter: at first. But the getting back a Path is IMHO much more intention revealing than a collection of strings. Especially because you're getting back an AbsolutePath or RelativePath which is even more intention revealing and something you may completely miss when splitting strings.
>
>
> absoluteArray := '/home/root/file' substrings: '/'.  "#('home' 'root' 'file')"
> relativeArray := ('home/root/file' substrings: '/').  "#('home' 'root' 'file')"
> "The distinction between absolute and relative is lost here!"
>
> absoluteArray = relativeArray.  "true"
> "Both paths may have referenced the same file - but also may not!!!!"
>
> absolutePath := Path from: '/home/root/file' delimiter: $/.  "Path / 'home' / 'root' / 'file'".
> absolutePath class.  "AbsolutePath"
> relativePath := Path from: 'home/root/file' delimiter: $/.  "Path * 'home' / 'root' / 'file'"
> relativePath class. "RelativePath".
> "The distinction between absolute and relative paths is kept.
> In #printString and class"
>
> absolutePath = relativePath.  "false"
> "No danger to confuse absolute and relative paths here"
>
>
>
> Or did I get you completely wrong?
>
> CU,
>
> Udo
>
>
>
>
> On 07/05/16 10:57, Sven Van Caekenberghe wrote:
>> Hi Udo,
>>
>> That is a very good explanation, thank you.
>>
>> I always had the impression that Path is not meant for public use, just part of the implementation. Should it not be part of the -Public package then ?
>>
>> Maybe there are still other ways to parse a Windows path while running on a Mac or Linux ?
>>
>> Sven
>>
>>> On 07 May 2016, at 10:46, Udo Schneider <[hidden email]> wrote:
>>>
>>> Hi Johan,
>>>
>>> I remember running into similar problems because I didn't understand the FileSystem philosophy ... and dealing with strings and concatenating them is so much easier, right? :-)
>>>
>>> After reading the chapter on FileSystem several times over and over again the IMHO most important part of it to get the grasp of FileSystem is on page 13 (http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/FileSystem.pdf):
>>>
>>> "
>>> FileReference = FileSystem + Path
>>> Paths and filesystems are the lowest level of the FileSystem API. A FileReference combines a path and a filesystem into a single object which provides a simpler protocol for working with files as we show in the previous section. References implement the path protocol with methods like /, parent and resolve:.
>>> "
>>>
>>> So in your example ‘/home/jfabry’ and ‘test/code/foo.txt’ are just (relative) path strings. They do not reference anything outside of the context of a filesystem. The hard part for me to understand was the fact that a path may not be unique. The same path might reference different files in different filesystems.
>>> This is especially strange coming from a *nix background where there is only one filesystem.
>>> But even on Windows one could argue that the OS nowadays only knows one filesystem: You can reference any file via a UNC path ... drives, shares, partitions, URIs and other filesystems are simply aliases into the UNC space.
>>> The nice thing of the FileSystem API is it's ability to transparently use files in-Memory, archives, FTP, WebDav, S3 ... . All from within Pharo with the same consistent API. E.g. if you have the FileSystemNetwork (http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork) installed you can do something like:
>>>
>>>
>>>
>>> "Obtain a FTP FileSystem"
>>> fs := FileSystem ftp: 'ftp://ftp.2600.com'.
>>>
>>> "Get working directory"
>>> wd := fs workingDirectory .
>>>
>>> "Print the following expression!"
>>> (wd /  'pub' / 'publications' / 'n0way') children.
>>> (wd /  'pub' / 'publications' / 'n0way' / 'README') contents.
>>>
>>> "Open a FileList on the FileSystem"
>>> FileList openOn: wd.
>>>
>>> "Remember to close if you are finished!"
>>> fs close.
>>>
>>>
>>>
>>>
>>> So to make a long story short: Both your strings contain paths. So we have to convert them into Paths and somehow combine them with a FileSystem to get a valid FileReference:
>>>
>>>
>>>
>>> "I changed the second string to demonstrate dealing with different delimiters"
>>> dirString := '/home/jfabry'.
>>> fileString := 'test\code\foo.txt'.
>>>
>>> "Convert path strings to Paths"
>>> dirPath := Path from: dirString delimiter: $/.
>>> filePath := Path from: fileString delimiter: $\.
>>> "Please note the Paths do not reference anything. We have no FileSystem context yet"
>>>
>>> "The FileSystem our Paths will be resolved within"
>>> diskFs := FileSystem disk.
>>>
>>> "FileReference for the root directory in the FS"
>>> rootRef := diskFs root.
>>>
>>> "Resolve our Paths in the Context of the Reference"
>>> dirRef := rootRef resolve: dirPath.
>>> fileRef := dirRef resolve: filePath. "File @ /home/jfabry/test/code/foo.txt"
>>>
>>> "Please note the fileRef printString. 'File' denotes the FileSystem - not the fact that this is a file! Then you have the path after the at sign"
>>>
>>>
>>>
>>>
>>>
>>> I hope this helps.
>>>
>>> Final advice: In Pharo you should *never never never* assume that a Path is "enough" to reference a file. You will always need the context (it's FileSystem) as well. And that's exactly what a FileReference (see above) is. So if you only have a Path it's questionable to assume that you can simply combine it with a DiskFileSystem to get a valid reference. What if the Path references a file in a ZIP in-Memory archive? Trying to access the Path on disk will yield no result. So always always always store/pass a FileReference if possible!!!!
>>> I did run into that issue in the past with archive/net FileSystems where some dev tools at one point extracted the Path from the FileReference and passed them arround. Down the stack some other methods needed the file contents. Because only the Path was passed they assumed they could retrieve the contents by simply combining it with a DiskFileSystem ... and boom!
>>>
>>>
>>> CU,
>>>
>>> Udo
>>>
>>>
>>> On 07/05/16 00:33, Johan Fabry wrote:
>>>> Hi all,
>>>>
>>>> I have a question about the filesystem that I could not resolve using the documentation. The problem is as follows: I have a file reference that is 2 separate strings that I need to join into one complete file ref but I don’t know how because I don’t know what the platform’s file separator is.
>>>>
>>>> For example, on a unix-like OS I get ‘/home/jfabry’ as one part and ‘test/code/foo.txt’ as the other part, and I need to construct a FileReference to ‘/home/jfabry/test/code/foo.txt’.On M$ I guess this would be 'C:\users\jfabry' and ‘test\code\foo.txt’, so I need to construct FileReference to  'C:\users\jfabry\test\code\foo.txt’
>>>>
>>>> And the bingo question is: what do I do if I both strings use different kinds of separators?
>>>>
>>>> TIA,
>>>>
>>>> ---> Save our in-boxes! http://emailcharter.org <---
>>>>
>>>> Johan Fabry   -   http://pleiad.cl/~jfabry
>>>> PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>
>>
>>
>
>
>