Let's say that I have a pod named foo with a resource file called test.sql in a directory sql. After compiling the pod, in fansh I create this Uri
uri1 := `fan://foo/sql/test.sql`
get does work
f2 := uri1.get as File
f2.readAllStr
SELECT * FROM FOO
but toFile does not work
uri1.toFile
sys::ArgErr: Invalid Uri scheme for local file: fan://foo/sql/test.sql
fan.sys.LocalFile.uriToFile (LocalFile.java:64)
fan.sys.File.make (File.java:26)
fan.sys.File.make (File.java:23)
fan.sys.Uri.toFile (Uri.java:1255)
Uri#.toFile is creating a File from the Uri and expects an Uri starting with file://. Although the doc says "Convenience for File.make(this) - no guarantee is made that the file exists." it seems to me counter-intuitive.
matthewThu 20 Jul 2017
If you are trying to get a file out of a Pod, use Pod.file
f := Pod.find("foo").file(`/sql/test.sql`)
SlimerDudeThu 20 Jul 2017
Confusingly, the following also works!
Pod.find("sys").file(`fan://foo/sql/test.sql`)
But Fraya mentioned that he can already get hold of a file in a pod, I think he just finds the semantics between Uri.get() and Uri.toFile() a bit unclear.
Uri.toFile() / File.make(Uri)
These are for files on the local file system - the standard files and directories on your computer. These don't need a scheme, and may be absolute or relative:
The "no guarantee is made that the file exists" part just means File objects may be instantiated regardless of whether the actual underlying system file exists or not. (Which has to be the case; because the file system is constantly changing and is not controlled by Fantom or Java, we can never be certain of what state it is in.)
// readme.moo doesn't exist, but no error is thrown
`/wot/ever/gibberish/readme.moo`.toFile()
Use File.exists() to check if the system file exists or not at any given point in time. (Be aware that other programs / processes (if they're evil enough) may create / delete the same files you're trying to use!)
Uri.get
Not all files are on the file system (think the Internet) and not all URIs point to files (URI is essentially a naming system). So Fantom lets you create your own Scheme where you can contribute to the URI namespace to resolve any kind of object.
(But Fantom and indexed properties are a poor man's IoC, so I don't really use it.)
As far as the fan:// scheme goes, think of it as resolving to a subclass of sys::File where the in() and various read() methods have been overridden to return content from the .pod file as oppose to the file system.
I think this is where the confusion is, and is perhaps a small leaky abstraction on Fantom's behalf. The public API just shows File but behind the scenes there is actually File (abstract class), LocalFile, MemFile, and ZipEntryFile.
I hope this helps, and if you want to suggest updates to the documentation that clarify matters, I'm sure Brian and Andy would be accommodating! :)
frayaFri 21 Jul 2017
I thank you all for your response.
@matthew: That's exactly what I was using. My confusion is about the semantics.
Maybe a warning in Uri#.toFileonly works for local filesystems or only works for file: Uris would helped me but I would prefer "more abstraction" even though "every abstraction leaks".
brianFri 21 Jul 2017
The semantics for Uri.toFile were convenience for File.make which is documented explicitly as constructor for local file system files only. But I see how it might be confusing, and really no good reason to have Uri.toFile not route to get in that case. I changed the logic for Uri.toFile to be:
public File toFile()
{
if (scheme == null) return File.make(this);
return (File)get();
}
fraya Thu 20 Jul 2017
Let's say that I have a pod named
foo
with a resource file calledtest.sql
in a directorysql
. After compiling the pod, infansh
I create thisUri
get
does workbut
toFile
does not workUri#.toFile
is creating aFile
from theUri
and expects anUri
starting withfile://
. Although the doc says "Convenience for File.make(this) - no guarantee is made that the file exists." it seems to me counter-intuitive.matthew Thu 20 Jul 2017
If you are trying to get a file out of a Pod, use
Pod.file
SlimerDude Thu 20 Jul 2017
Confusingly, the following also works!
But Fraya mentioned that he can already get hold of a file in a pod, I think he just finds the semantics between
Uri.get()
andUri.toFile()
a bit unclear.Uri.toFile() / File.make(Uri)
These are for files on the local file system - the standard files and directories on your computer. These don't need a scheme, and may be absolute or relative:
The "no guarantee is made that the file exists" part just means File objects may be instantiated regardless of whether the actual underlying system file exists or not. (Which has to be the case; because the file system is constantly changing and is not controlled by Fantom or Java, we can never be certain of what state it is in.)
Use
File.exists()
to check if the system file exists or not at any given point in time. (Be aware that other programs / processes (if they're evil enough) may create / delete the same files you're trying to use!)Uri.get
Not all files are on the file system (think the Internet) and not all URIs point to files (URI is essentially a naming system). So Fantom lets you create your own Scheme where you can contribute to the URI namespace to resolve any kind of object.
(But Fantom and indexed properties are a poor man's IoC, so I don't really use it.)
As far as the
fan://
scheme goes, think of it as resolving to a subclass ofsys::File
where thein()
and variousread()
methods have been overridden to return content from the .pod file as oppose to the file system.I think this is where the confusion is, and is perhaps a small leaky abstraction on Fantom's behalf. The public API just shows
File
but behind the scenes there is actuallyFile (abstract class)
,LocalFile
,MemFile
, andZipEntryFile
.I hope this helps, and if you want to suggest updates to the documentation that clarify matters, I'm sure Brian and Andy would be accommodating! :)
fraya Fri 21 Jul 2017
I thank you all for your response.
@matthew: That's exactly what I was using. My confusion is about the semantics.
@SlimerDude: My expectation on
Uri#.toFile
is that if anUri
can be converted to aFile
like fan://foo/sql/test.sql or https://bitbucket.org/AlienFactory/afgundam/downloads/afGundam-2.1.2.zip (in a future http Uri), either I have aFile
or a null or anErr
if it is not possible to create the file.Maybe a warning in
Uri#.toFile
only works for local filesystems or only works for file: Uris would helped me but I would prefer "more abstraction" even though "every abstraction leaks".brian Fri 21 Jul 2017
The semantics for Uri.toFile were convenience for File.make which is documented explicitly as constructor for local file system files only. But I see how it might be confusing, and really no good reason to have Uri.toFile not route to get in that case. I changed the logic for Uri.toFile to be:
fraya Sat 22 Jul 2017
It make sense, thank you for your work.