Resource confusion

N

Novice

I'm having trouble figuring out the best way of obtaining existing files
for my program to use.

My program, which is a game, wants to open an input file that drives the
game. Any number of input files may exist but they'll typically be stored
in the same directory, although the user may choose to put supplementary
input files in different directories. I provide a preference dialog where
the user can indicate the directory which will serve as the starting
point for the file chooser that selects the input file to be used in
playing the game.

The program needs to work when I am testing in Eclipse and it also needs
to work when the program is executing in a production environment. I
expect that it will run via Java Web Start, a JNLP file, and a jar. (I'm
using a self-signed test certificate for now and granting all-permissions
via the JNLP file.)

At the moment, my preferences dialog allows the user to choose a
directory (or a directory and a file) that will serve as the starting
point for the file chooser that will be used by the Open logic that opens
the input file. The value of that starting point is being correctly
stored by my program and can be changed successfully via the preferences
dialog. But I'm not having any luck actually obtaining the file via my
current code. Given that the file name may include accented letters, it
seems necessary to decode it with UTF-8 so my code proceeds as follows:

=========================================================================
String phraseListStartPoint = this.userPrefs.get
(PHRASE_LIST_STARTPOINT_KEY, PHRASE_LIST_STARTPOINT_VALUE);
URL phraseListURL = this.getClass().getResource(phraseListStartPoint);
String encodedFileName = null;
String decodedFileName = null;
try {
encodedFileName = phraseListURL.getFile();
decodedFileName = URLDecoder.decode(encodedFileName, "UTF-8");
}
catch (NullPointerException npe_excp) {
this.logger.logp(Level.WARNING, this.CLASS_NAME, METHOD_NAME,
"Phrase list URL, " + phraseListStartPoint + ", does not exist. Using
default directory instead.");
}
catch (UnsupportedEncodingException ue_excp) {
this.logger.logp(Level.WARNING, this.CLASS_NAME, METHOD_NAME,
"Failed to decode file name " + encodedFileName, ue_excp);
System.exit(16);
}

File startPoint = null;
if (decodedFileName != null) startPoint = new File(decodedFileName);
else startPoint = new File(System.getProperty("user.home"));

/* Launch the file chooser, open the file, read it..... */
=========================================================================


This code inevitably reveals that phraseListURL is null, even though the
value of PHRASE_LIST_STARTPOINT_VALUE is a path found on my file system
such as C:\Games\PhraseLists.

Clearly, this.getClass().getResource(phraseListStartPoint) is failing to
work as I would like.

I've tried reading the API on the getResource() method of the Class class
but I'm not following it. I know nothing about class loaders or which one
is the right one to use when. I'm not even sure I should be using an
approach like this to access a file that is in the file system.

I might bundle a few sample input files into the jar when I make this
game publicly accessible via Java Web Start but I mean those only to be
examples that players can use to build their own input files. Therefore,
I don't think they'll be accessing their own files from within the jar
but rather from the file system on their own computer. So I need the best
way to code the access to this file regardless of whether it is in a jar
or on the file system locally.

Can anyone get me going in the right direction on this? Maybe a few
general remarks about best practices and then suggestions on where to go
to find the exact techniques I'll need?
 
A

Arved Sandstrom

On 12-01-28 01:47 PM, Novice wrote:
[ SNIP ]
String phraseListStartPoint = this.userPrefs.get
(PHRASE_LIST_STARTPOINT_KEY, PHRASE_LIST_STARTPOINT_VALUE);
URL phraseListURL = this.getClass().getResource(phraseListStartPoint); [ ... ]

File startPoint = null;
if (decodedFileName != null) startPoint = new File(decodedFileName);
else startPoint = new File(System.getProperty("user.home"));

/* Launch the file chooser, open the file, read it..... */
=========================================================================


This code inevitably reveals that phraseListURL is null, even though the
value of PHRASE_LIST_STARTPOINT_VALUE is a path found on my file system
such as C:\Games\PhraseLists.

Clearly, this.getClass().getResource(phraseListStartPoint) is failing to
work as I would like.

I've tried reading the API on the getResource() method of the Class class
but I'm not following it. I know nothing about class loaders or which one
is the right one to use when. I'm not even sure I should be using an
approach like this to access a file that is in the file system.
[ SNIP ]

If you're going to use .getResource(), the String "name" that you supply
is actually a '/'-separated path name that identifies something on a
classloader classpath. You have a number of classloaders involved every
time you run your app; fact is that your phrase-list file (even if you
had a '/'-separated path spec for it) very likely isn't on the classpath
for any of those classloaders.

It doesn't sound to me like you need either the getResource() or
getResourceAsStream() approaches (which are available through
ClassLoader or delegated from Class); you might be better off saving and
using file URLs.

The exact form of a file URL varies across systems but they all have the
file: scheme. On a UNIX system

URL phraseListUrl = new URL("file:///home/me/Games/PhraseLists");

would work, but off the top of my head on a Windows box it's something like

URL phraseListUrl = new URL("file:///C:/Games/PhraseLists");

This is just informational, because your app doesn't have to construct
these things, just save them. Your user does the heavy lifting by
selecting the location with a file chooser; that gives you a File
object. You can save out the result with

userSelectedFile.toURI().toURL().toString()

To return to getResource() or getResourceAsStream(), and classloaders:
the situation is more complicated in Java application server
environments [1], and for this reason context classloaders were made
available as (imperfect) solutions. But you are not in that scenario.

I'll also add that *if* it made sense for you to have a file resource on
the classpath, and you were using getResource() or
getResourceAsStream(), it doesn't make sense for you to pose the
question "which classloader should I use?" That's not *your* decision to
make, per se - you can influence that choice by where you place the
resource, but you don't directly select a classloader (again, unless you
were in a server environment and using a context classloader).

AHS

1. As anyone can attest who has spent quality hours wrestling with a
situation where instance 1 of class X hasn't the same class as instance
2 of class X...for various reasons.
 
L

Lew

Arved said:
If you're going to use .getResource(), the String "name" that you supply
is actually a '/'-separated path name that identifies something on a
classloader classpath. You have a number of classloaders involved every
time you run your app; fact is that your phrase-list file (even if you
had a '/'-separated path spec for it) very likely isn't on the classpath
for any of those classloaders.

It doesn't sound to me like you need either the getResource() or
getResourceAsStream() approaches (which are available through
ClassLoader or delegated from Class); you might be better off saving and
using file URLs.

The exact form of a file URL varies across systems but they all have the
file: scheme. On a UNIX system

URL phraseListUrl = new URL("file:///home/me/Games/PhraseLists");

would work, but off the top of my head on a Windows box it's something like

URL phraseListUrl = new URL("file:///C:/Games/PhraseLists");

This is just informational, because your app doesn't have to construct
these things, just save them. Your user does the heavy lifting by
selecting the location with a file chooser; that gives you a File
object. You can save out the result with

userSelectedFile.toURI().toURL().toString()

To return to getResource() or getResourceAsStream(), and classloaders:
the situation is more complicated in Java application server
environments [1], and for this reason context classloaders were made
available as (imperfect) solutions. But you are not in that scenario.

I'll also add that *if* it made sense for you to have a file resource on
the classpath, and you were using getResource() or
getResourceAsStream(), it doesn't make sense for you to pose the
question "which classloader should I use?" That's not *your* decision to
make, per se - you can influence that choice by where you place the
resource, but you don't directly select a classloader (again, unless you
were in a server environment and using a context classloader).

AHS

1. As anyone can attest who has spent quality hours wrestling with a
situation where instance 1 of class X hasn't the same class as instance
2 of class X...for various reasons.

What he said, only adding tangentially that at some not-too-distant future
point it pays to understand classloading in Java.
 
N

Novice

On 12-01-28 01:47 PM, Novice wrote:
[ SNIP ]
String phraseListStartPoint = this.userPrefs.get
(PHRASE_LIST_STARTPOINT_KEY, PHRASE_LIST_STARTPOINT_VALUE);
URL phraseListURL =
this.getClass().getResource(phraseListStartPoint); [ ... ]

File startPoint = null;
if (decodedFileName != null) startPoint = new File(decodedFileName);
else startPoint = new File(System.getProperty("user.home"));

/* Launch the file chooser, open the file, read it..... */
======================================================================
===


This code inevitably reveals that phraseListURL is null, even though
the value of PHRASE_LIST_STARTPOINT_VALUE is a path found on my file
system such as C:\Games\PhraseLists.

Clearly, this.getClass().getResource(phraseListStartPoint) is failing
to work as I would like.

I've tried reading the API on the getResource() method of the Class
class but I'm not following it. I know nothing about class loaders or
which one is the right one to use when. I'm not even sure I should be
using an approach like this to access a file that is in the file
system.
[ SNIP ]

If you're going to use .getResource(), the String "name" that you
supply is actually a '/'-separated path name that identifies something
on a classloader classpath. You have a number of classloaders involved
every time you run your app; fact is that your phrase-list file (even
if you had a '/'-separated path spec for it) very likely isn't on the
classpath for any of those classloaders.

It doesn't sound to me like you need either the getResource() or
getResourceAsStream() approaches (which are available through
ClassLoader or delegated from Class); you might be better off saving
and using file URLs.

The exact form of a file URL varies across systems but they all have
the file: scheme. On a UNIX system

URL phraseListUrl = new URL("file:///home/me/Games/PhraseLists");

would work, but off the top of my head on a Windows box it's something
like

URL phraseListUrl = new URL("file:///C:/Games/PhraseLists");

This is just informational, because your app doesn't have to construct
these things, just save them. Your user does the heavy lifting by
selecting the location with a file chooser; that gives you a File
object. You can save out the result with

userSelectedFile.toURI().toURL().toString()

Thanks, Arved, that was VERY helpful. First, I tried just hard-coding the
path with the "file:/" (only needed one forward slash, not all three,
although I've seen three used on other occasions) and that worked fine.
Then I tried your trick with adding the .toURI().toURL() (I found I
didn't need the final toString()) and that also worked very well. I
haven't tried it outside of Eclipse yet but if it works as well from Java
Web Start and on an OS other than Windows, I should be golden.
To return to getResource() or getResourceAsStream(), and classloaders:
the situation is more complicated in Java application server
environments [1], and for this reason context classloaders were made
available as (imperfect) solutions. But you are not in that scenario.

I'll also add that *if* it made sense for you to have a file resource
on the classpath, and you were using getResource() or
getResourceAsStream(), it doesn't make sense for you to pose the
question "which classloader should I use?" That's not *your* decision
to make, per se - you can influence that choice by where you place the
resource, but you don't directly select a classloader (again, unless
you were in a server environment and using a context classloader).
In all honesty, I have never seriously looked at classloaders and have no
real idea why there are all various different ones and when I should be
trying to use one programmatically. I basically had troubles reading a
file from my file system some time ago, googled, and found a post with an
example indicating that toClass().toResource() was a good idea. (A
specific mention of classLoader may have been in there too.) I never
really understood the issue properly but that code got me out of trouble
for the original situation and I've imitated it several times without
really understanding it. Learning more about these classloaders is on my
To Do list; maybe I need to move it up the list ;-)
AHS

1. As anyone can attest who has spent quality hours wrestling with a
situation where instance 1 of class X hasn't the same class as
instance 2 of class X...for various reasons.


Thanks again Arved! I think I'm out of trouble now....
 
L

Lew

Novice said:
In all honesty, I have never seriously looked at classloaders and have no
real idea why there are all various different ones and when I should be
trying to use one programmatically. I basically had troubles reading a
file from my file system some time ago, googled, and found a post with an
example indicating that toClass().toResource() was a good idea. (A
specific mention of classLoader may have been in there too.) I never
really understood the issue properly but that code got me out of trouble
for the original situation and I've imitated it several times without
really understanding it. Learning more about these classloaders is on my
To Do list; maybe I need to move it up the list ;-)

The term for this style of programming is "cargo cult programming".

Programming by superstition is not a winning strategy.

Everything in programming is explicable. There is an answer. Be confident of
that. So never, ever, ever accept "I never really understood the issue
properly", much less rely on code you don't understand to get you out of
trouble. At least not for very long.

"I've imitated it several times without really understanding it" is criminal.
Criminal. That's not how a programmer works.
Thanks again Arved! I think I'm out of trouble now....

Not yet.
 
A

Arved Sandstrom

On 12-01-28 01:47 PM, Novice wrote:
[ SNIP ]
String phraseListStartPoint = this.userPrefs.get
(PHRASE_LIST_STARTPOINT_KEY, PHRASE_LIST_STARTPOINT_VALUE);
URL phraseListURL =
this.getClass().getResource(phraseListStartPoint); [ ... ]

File startPoint = null;
if (decodedFileName != null) startPoint = new File(decodedFileName);
else startPoint = new File(System.getProperty("user.home"));

/* Launch the file chooser, open the file, read it..... */
======================================================================
===


This code inevitably reveals that phraseListURL is null, even though
the value of PHRASE_LIST_STARTPOINT_VALUE is a path found on my file
system such as C:\Games\PhraseLists.

Clearly, this.getClass().getResource(phraseListStartPoint) is failing
to work as I would like.

I've tried reading the API on the getResource() method of the Class
class but I'm not following it. I know nothing about class loaders or
which one is the right one to use when. I'm not even sure I should be
using an approach like this to access a file that is in the file
system.
[ SNIP ]

If you're going to use .getResource(), the String "name" that you
supply is actually a '/'-separated path name that identifies something
on a classloader classpath. You have a number of classloaders involved
every time you run your app; fact is that your phrase-list file (even
if you had a '/'-separated path spec for it) very likely isn't on the
classpath for any of those classloaders.

It doesn't sound to me like you need either the getResource() or
getResourceAsStream() approaches (which are available through
ClassLoader or delegated from Class); you might be better off saving
and using file URLs.

The exact form of a file URL varies across systems but they all have
the file: scheme. On a UNIX system

URL phraseListUrl = new URL("file:///home/me/Games/PhraseLists");

would work, but off the top of my head on a Windows box it's something
like

URL phraseListUrl = new URL("file:///C:/Games/PhraseLists");

This is just informational, because your app doesn't have to construct
these things, just save them. Your user does the heavy lifting by
selecting the location with a file chooser; that gives you a File
object. You can save out the result with

userSelectedFile.toURI().toURL().toString()

Thanks, Arved, that was VERY helpful. First, I tried just hard-coding the
path with the "file:/" (only needed one forward slash, not all three,
although I've seen three used on other occasions) and that worked fine.
Then I tried your trick with adding the .toURI().toURL() (I found I
didn't need the final toString()) and that also worked very well. I
haven't tried it outside of Eclipse yet but if it works as well from Java
Web Start and on an OS other than Windows, I should be golden.

It won't be the only approach that works, Java file handling offers a
whole bunch of techniques. Your basic starting point (for this specific
scenario) is

File userSelectedFile = myFileChooser.getSelectedFile();

You don't have to go the URI/URL route for your scenario. It's useful to
be aware of file URIs/URLs, because in some situations you need to use
them, but here you don't.

What else could you have done? Again, starting with a user-provided File
object. Well, consider the full java.io.File API and what your
circumstances are. Note: if you've got JDK 7 then consider
java.io.file.Path (and things like Path.toRealPath(boolean)).

In your case (user files being saved on their own PC for their own use)
you'd probably do just fine with File.getAbsolutePath(). *But*, and this
is a big "but", my initial solution (and presumably your own attempts)
didn't overly consider the nature of the File object returned from
JFileChooser.getSelectedFile().

Bear in mind - and the java.io.File Javadocs make this abundantly clear
- that File objects are _abstract_. IOW, you (or the user) can freely
construct a File that refers to something that doesn't exist. And
because most of the look & feels for JFC/AWT provide a user-typing
option in the Open file chooser, it's possible for the user to provide a
path that translates to a File that refers to something that doesn't exist.

So also consider using the File.exists() method, and act accordingly.
To return to getResource() or getResourceAsStream(), and classloaders:
the situation is more complicated in Java application server
environments [1], and for this reason context classloaders were made
available as (imperfect) solutions. But you are not in that scenario.

I'll also add that *if* it made sense for you to have a file resource
on the classpath, and you were using getResource() or
getResourceAsStream(), it doesn't make sense for you to pose the
question "which classloader should I use?" That's not *your* decision
to make, per se - you can influence that choice by where you place the
resource, but you don't directly select a classloader (again, unless
you were in a server environment and using a context classloader).
In all honesty, I have never seriously looked at classloaders and have no
real idea why there are all various different ones and when I should be
trying to use one programmatically. I basically had troubles reading a
file from my file system some time ago, googled, and found a post with an
example indicating that toClass().toResource() was a good idea. (A
specific mention of classLoader may have been in there too.) I never
really understood the issue properly but that code got me out of trouble
for the original situation and I've imitated it several times without
really understanding it. Learning more about these classloaders is on my
To Do list; maybe I need to move it up the list ;-)
AHS

1. As anyone can attest who has spent quality hours wrestling with a
situation where instance 1 of class X hasn't the same class as
instance 2 of class X...for various reasons.

Thanks again Arved! I think I'm out of trouble now....

Like Lew said, you're probably not. :)

To follow up the discussion above, if you continue to pursue a Java
career you will soon situations where your file of interest (perhaps a
..properties or XML configuration file) is inside your executable JAR, or
any JAR. Or maybe you're in a full-blown Java EE environment and that
same configuration file is packaged in a WAR or an EJB JAR, or for some
other reasons it's made available on the server classpath, or what have you.

I wouldn't defer a consideration of classloaders at all. I think
everyone should start with reading Chapter 12 "Execution" of the Java
Language Specification (e.g.
http://java.sun.com/docs/books/jls/third_edition/html/execution.html).
This is important, foundational stuff, and you're ahead of the game if
you read it and understand it.

Also, see the JVM spec:
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html.
Although all of it is interesting, for classloading you want to peruse
Chapter 5 "Loading, Linking and Initializing". In particular Section 5.3.

Read the API Javadoc for java.lang.ClassLoader.

Read some decent articles on Java classloading, either for stock Java SE
situations, or for Java EE + any docs that pertain to your particular
app server. This link
(http://www.ibm.com/developerworks/java/library/j-dyn0429/) is a fairly
good article.

AHS
 
R

Roedy Green

I'm having trouble figuring out the best way of obtaining existing files
for my program to use.

I would put the read-only config files in a resource in a jar. This
means they can't get lost and they work even if the user is not
capable of configuring his own files. They are also compact. They get
updated automatically when you update the program.

You problem then becomes, where to put the user's files. JNLP lets
you allocate some space with a hideous name, not really suitable for
the user to insert things except via your game. If he creates them
with a text editor you might import them into that space or store the
filenames (not files) in your own space so he can pick them off a menu
by unqualified name, and you then go fetch them from the original
locations as needed.
 
M

Martin Gregorie

I would put the read-only config files in a resource in a jar. This
means they can't get lost and they work even if the user is not capable
of configuring his own files. They are also compact. They get updated
automatically when you update the program.

You problem then becomes, where to put the user's files. JNLP lets you
allocate some space with a hideous name, not really suitable for the
user to insert things except via your game. If he creates them with a
text editor you might import them into that space or store the filenames
(not files) in your own space so he can pick them off a menu by
unqualified name, and you then go fetch them from the original locations
as needed.
Same here: I'd put the defaults in the jar and, allow the user to put
overriding files in a master location and a one local to the user: if it
was a UNIX type system the master location would be /usr/local/etc and
the local location would be the hidden directory ~/.myapp and the program
would use a search something like this;

List<String> config = new List<String>();
config.add("~/.myapp/config.txt");
config.add("/usr/local/etc/config.txt");

boolean found = false;
for (String s : config)
{
File cf = new File(s);
if (cf.exists())
{
found = true;
// use the configuration in cf
}
}

if (!found)
// use the default configuration held as a resource in the jar file

which lets the user's configuration take preference over the site
configuration in /usr/local/etc, which in turn takes precedence over the
jar file resource.

NOTE: this assumes that each configuration is complete.

Another way to do it is to read all three config files in the *reverse*
order (from jar file, then /usr/local/etc and finally from ~/.myapp) with
items read from an earlier file being overwritten by matching items from
a later file. This approach means that the config in the jar file must
give a default value for every item, but the site and user configurations
only need to provide values for items they want to customise.
 
A

Arved Sandstrom

Same here: I'd put the defaults in the jar and, allow the user to put
overriding files in a master location and a one local to the user: if it
was a UNIX type system the master location would be /usr/local/etc and
the local location would be the hidden directory ~/.myapp and the program
would use a search something like this;

List<String> config = new List<String>();
config.add("~/.myapp/config.txt");
config.add("/usr/local/etc/config.txt");

boolean found = false;
for (String s : config)
{
File cf = new File(s);
if (cf.exists())
{
found = true;
// use the configuration in cf
}
}

if (!found)
// use the default configuration held as a resource in the jar file

which lets the user's configuration take preference over the site
configuration in /usr/local/etc, which in turn takes precedence over the
jar file resource.

NOTE: this assumes that each configuration is complete.

Another way to do it is to read all three config files in the *reverse*
order (from jar file, then /usr/local/etc and finally from ~/.myapp) with
items read from an earlier file being overwritten by matching items from
a later file. This approach means that the config in the jar file must
give a default value for every item, but the site and user configurations
only need to provide values for items they want to customise.
This is the way I would do things too, in general, for a configuration
file problem. One wants the average user to do as little as possible -
preferably nothing - with a file system, because a large percentage of
users don't get file systems.

I'll point out that the OP has a situation, as he/she has described it,
where there are *several/many* input files that can configure _a_ game,
and one of them is selected to configure a given game. This is not
atypical for games with numerous scenarios. Although on the UI level it
would certainly be desirable to present the user with a dropdown of
selections, rather than a file chooser, the OP's problem seems to be one
of reading *data* files, not one of reading a handful of true
configuration files. And his actual questions start with the details of
how best to _read_ a file, as I understand it.

AHS
 
M

Martin Gregorie

This is the way I would do things too, in general, for a configuration
file problem. One wants the average user to do as little as possible -
preferably nothing - with a file system, because a large percentage of
users don't get file systems.

I'll point out that the OP has a situation, as he/she has described it,
where there are *several/many* input files that can configure _a_ game,
and one of them is selected to configure a given game. This is not
atypical for games with numerous scenarios. Although on the UI level it
would certainly be desirable to present the user with a dropdown of
selections, rather than a file chooser, the OP's problem seems to be one
of reading *data* files, not one of reading a handful of true
configuration files. And his actual questions start with the details of
how best to _read_ a file, as I understand it.
Point, but the logic is still the same regardless of whether the file is
a configuration or a (set of) data files, since he seems to be talking
about a two level hierarchy of files where a local copy, if there is one,
takes priority over one in the jar file.

You can see a situation in which the first run can only find the copy in
the jar file and, in the course of the run, creates a modified local
version which is what it should use for all subsequent runs. In that case
I think my first suggestion would be the appropriate one and, again,
would work regardless of whether the file contains a few items
(configuration) or a lot (data).

One thing the OP may have missed is that, if the jarfile is intended to
be handed to a site admin who then distributes it to a set of users,
there may be a good case for providing a sysadmin tool that can extract
the file(s) from the jar file, apply site-specific, site-wide
customisations to them and put the result back in the jar file. Something
like this can make the package a lot easier to install.

Perhaps the most obvious example of this being a good idea would be if
its a client-server app: the site-wide customisation tool would let the
sysadmin put the site's server hostname etc. into the jar file before
distributing it to the user community. The effect is that the app should
'just run' on installation, making the users happy and saving the helldesk
from an endless stream of "why can't X find the server?" queries.
 
A

Arved Sandstrom

Point, but the logic is still the same regardless of whether the file is
a configuration or a (set of) data files, since he seems to be talking
about a two level hierarchy of files where a local copy, if there is one,
takes priority over one in the jar file.

You can see a situation in which the first run can only find the copy in
the jar file and, in the course of the run, creates a modified local
version which is what it should use for all subsequent runs. In that case
I think my first suggestion would be the appropriate one and, again,
would work regardless of whether the file contains a few items
(configuration) or a lot (data).

One thing the OP may have missed is that, if the jarfile is intended to
be handed to a site admin who then distributes it to a set of users,
there may be a good case for providing a sysadmin tool that can extract
the file(s) from the jar file, apply site-specific, site-wide
customisations to them and put the result back in the jar file. Something
like this can make the package a lot easier to install.

Perhaps the most obvious example of this being a good idea would be if
its a client-server app: the site-wide customisation tool would let the
sysadmin put the site's server hostname etc. into the jar file before
distributing it to the user community. The effect is that the app should
'just run' on installation, making the users happy and saving the helldesk
from an endless stream of "why can't X find the server?" queries.
Points. :)

There are really 2 discussions here: where to put files, and how to read
them from where you put them. I was focusing initially more on the
reading bit, because I got the impression that's what the OP was really
wrestling with.

As far as the initial provision and bundling of configuration/data files
I'd be generally inclined to agree with you. And of course there isn't
any reason why a ream of "data" files that define different
user-selectable configurations couldn't be bundled in a JAR.

AHS
 
M

Martin Gregorie

There are really 2 discussions here: where to put files, and how to read
them from where you put them. I was focusing initially more on the
reading bit, because I got the impression that's what the OP was really
wrestling with.
Yes, I agree he was having problems with JFileChooser, but he also had
the resource files in the mix from the start, thought they weren't
obvious since they were described in a block of test after his initial
chunk of problem text.

However, looking back that far, I'm not certain that the OP ever spelled
out the relationship between the resource files and the user-supplied
external files. I think you assumed that they were co-equal while I
assumed some sort of precedence relationship.

It would be helpful if the OP described that relationship.
As far as the initial provision and bundling of configuration/data files
I'd be generally inclined to agree with you. And of course there isn't
any reason why a ream of "data" files that define different
user-selectable configurations couldn't be bundled in a JAR.
Indeed, but the resource file:external file relationship is key to the
understanding since that determines how they would be selected.

At a guess, either JFileChooser see resource files or there is a
different chooser (mandatory for JWS services) that can, but a somewhat
hasty scan of the Javadocs and tutorial suggests that separate chooser
instances would be needed for resource files and external files.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top