Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #11631

Re: Resource confusion

From Arved Sandstrom <asandstrom3minus1@eastlink.ca>
Newsgroups comp.lang.java.programmer
Subject Re: Resource confusion
References <Xns9FE8824D28F28jpnasty@94.75.214.39> <UeYUq.127$V94.98@newsfe21.iad> <Xns9FE96DE332EEjpnasty@94.75.214.39>
Message-ID <nhfVq.3186$Qb1.42@newsfe20.iad> (permalink)
Organization Public Usenet Newsgroup Access
Date 2012-01-29 13:24 -0400

Show all headers | View raw


On 12-01-29 01:40 AM, Novice wrote:
> Arved Sandstrom <asandstrom3minus1@eastlink.ca> wrote in
> news:UeYUq.127$V94.98@newsfe21.iad: 
> 
>> 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
-- 
...wherever the people are well informed they can be trusted with their
own government...
-- Thomas Jefferson, 1789

Back to comp.lang.java.programmer | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Resource confusion Novice <novice@example..com> - 2012-01-28 17:47 +0000
  Re: Resource confusion Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-28 15:44 -0400
    Re: Resource confusion Lew <noone@lewscanon.com> - 2012-01-28 13:43 -0800
    Re: Resource confusion Novice <novice@example..com> - 2012-01-29 05:40 +0000
      Re: Resource confusion Lew <noone@lewscanon.com> - 2012-01-28 22:43 -0800
      Re: Resource confusion Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-29 13:24 -0400
  Re: Resource confusion Roedy Green <see_website@mindprod.com.invalid> - 2012-01-30 13:33 -0800
    Re: Resource confusion Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-31 02:45 +0000
      Re: Resource confusion Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-31 06:32 -0400
        Re: Resource confusion Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-31 20:43 +0000
          Re: Resource confusion Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-31 18:08 -0400
            Re: Resource confusion Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-31 23:01 +0000

csiph-web