[Pharo-users] How to construct a multi-part file reference

Udo Schneider udo.schneider at homeaddress.de
Sat May 7 04:46:50 EDT 2016

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 

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 
(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 
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!



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

More information about the Pharo-users mailing list