JDK-4614196 : FileNotFoundException.getName() to return missing file name
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.4.0,6
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic,solaris_7
  • CPU: generic
  • Submitted: 2001-12-15
  • Updated: 2009-04-28
Description
When I catch a java.io.FileNotFoundException, it would be nice to get the 
file name.  As it stands, the detail message from 
	FileInputStream.open(String name) 
contains the file name AND an English-language diagnostic.  Very difficult
for me to internationalize my program (javac) when that's all I have to work 
with.
Suggested fix from java.net member: leouser

A DESCRIPTION OF THE FIX :
BUG ID: 4614196 wanted: a method on java.io.FileNotFoundException that returns file name

files altered: java.io.FileNotFoundException
JDK Version: jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin

Discusion:
/**
 * BUG ID:4614196 wanted: a method on java.io.FileNotFoundException that returns file name
 * This RFE makes perfect sense to implement.  There should definately be a way
 * for the user to be able to determine what File was not found with this exception.
 * Without this method the user is forced to parse the message that comes with
 * the Exception, which is not a good way of doing things.
 *
 * The test cases show that the new functionality integrates well with the common
 * classes that would throw this Exception: RandomAccessFile and FileInputStream.
 * The developer can easily use the File instance returned to create a variety
 * of messages or if the policy fits, create the File itself.  I choose returning
 * a File over a String because it is instantly more usuable.  With a File instance
 * the user can get different representations of the path to the non existent
 * file instead of being forced with one representation right of the bat.
 *
 * ISSUES:
 * It is possible that the getFile method will return null.  This is unavoidable
 * at this juncture, FileNotFoundException has 2 constructors in existences that
 * take nothing or just a message.  The javadoc clearly warns that getFile may
 * return null if the instance was constructed without a File instance.  This
 * hopefully will be sufficient, there is no way around this problem.  You cannot
 * construct a File instance with no information.
 *
 * Another issue is that FileNotFoundException is not final.  As always any subclass
 * of FileNotFoundException may have added a getFile method which this one may
 * somehow conflict with, though dubious it may seem.
 *
 * TESTING PLAN:
 * We exercise the getFile method via getting an Exception tossed through
 * the FileInputStream and RandomAccessFile constructors.  They are constructed
 * with a File pointing to "BoggaWoooga.txt", which must not exist on the
 * filesystem if this test is to succeed.  This also highlights how well
 * the new method integrates with the existing infrastructure.  We also test
 * the new constructor to prove that the getFile method will return a File
 * when it is created through it.  We also test an old constructor to prove
 * that it will return null.
 *
 * java.io.FileNotFoundException modified against:
 * jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
 *
 * and also executed on a Suse Linux 7.3 distribution.
 *
 * Brian Harry
 * ###@###.###
 * JAN 6, 2006
 *
 */

unified diff:
--- /home/nstuff/java6/jdk1.6.0/java/io/FileNotFoundException.java	Thu Dec 15 02:16:36 2005
+++ /home/javarefs/java/io/FileNotFoundException.java	Fri Jan  6 13:13:59 2006
@@ -24,7 +24,8 @@
  */
 
 public class FileNotFoundException extends IOException {
-
+    
+    private File path;
     /**
      * Constructs a <code>FileNotFoundException</code> with
      * <code>null</code> as its error detail message.
@@ -47,6 +48,23 @@
     }
 
     /**
+     * Constructs a <code>FileNotFoundException</code> with
+     * a File instance pointing towards the nonexistent file and the
+     * specified detail message. The string <code>s</code> can be
+     * retrieved later by the
+     * <code>{@link java.lang.Throwable#getMessage}</code>
+     * method of class <code>java.lang.Throwable</code>.
+     * The File can be retrieved later by the getFile method.
+     *
+     * @param   path the File that was not found.
+     * @param   s   the detail message.
+     */
+    public FileNotFoundException(File path, String s){
+	super(s);
+	this.path = path;
+    }
+
+    /**
      * Constructs a <code>FileNotFoundException</code> with a detail message
      * consisting of the given pathname string followed by the given reason
      * string.  If the <code>reason</code> argument is <code>null</code> then
@@ -59,6 +77,20 @@
 	super(path + ((reason == null)
 		      ? ""
 		      : " (" + reason + ")"));
+	this.path = new File(path);
+    }
+    
+    /**
+     * Returns a File instance indicating the ile that could not
+     * be found.  Warning: if the FileNotFoundException was not constructed
+     * with path information then this method will return null.  Hence
+     * when called, the return value should always be tested.
+     *
+     * @returns a File pointing towards the filesystem location where the
+     *          File was not found.
+     */
+    public File getFile(){
+	return path;
     }
 
 }


JUnit TESTCASE :
import junit.framework.TestCase;
import junit.textui.TestRunner;
import java.io.*;
import static java.lang.System.out;


/**
 * BUG ID:4614196 wanted: a method on java.io.FileNotFoundException that returns file name
 * This RFE makes perfect sense to implement.  There should definately be a way
 * for the user to be able to determine what File was not found with this exception.
 * Without this method the user is forced to parse the message that comes with
 * the Exception, which is not a good way of doing things.
 *
 * The test cases show that the new functionality integrates well with the common
 * classes that would throw this Exception: RandomAccessFile and FileInputStream.
 * The developer can easily use the File instance returned to create a variety
 * of messages or if the policy fits, create the File itself.  I choose returning
 * a File over a String because it is instantly more usuable.  With a File instance
 * the user can get different representations of the path to the non existent
 * file instead of being forced with one representation right of the bat.
 *
 * ISSUES:
 * It is possible that the getFile method will return null.  This is unavoidable
 * at this juncture, FileNotFoundException has 2 constructors in existences that
 * take nothing or just a message.  The javadoc clearly warns that getFile may
 * return null if the instance was constructed without a File instance.  This
 * hopefully will be sufficient, there is no way around this problem.  You cannot
 * construct a File instance with no information.
 *
 * Another issue is that FileNotFoundException is not final.  As always any subclass
 * of FileNotFoundException may have added a getFile method which this one may
 * somehow conflict with, though dubious it may seem.
 *
 * TESTING PLAN:
 * We exercise the getFile method via getting an Exception tossed through
 * the FileInputStream and RandomAccessFile constructors.  They are constructed
 * with a File pointing to "BoggaWoooga.txt", which must not exist on the
 * filesystem if this test is to succeed.  This also highlights how well
 * the new method integrates with the existing infrastructure.  We also test
 * the new constructor to prove that the getFile method will return a File
 * when it is created through it.  We also test an old constructor to prove
 * that it will return null.
 *
 * java.io.FileNotFoundException modified against:
 * jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
 *
 * and also executed on a Suse Linux 7.3 distribution.
 *
 * Brian Harry
 * ###@###.###
 * JAN 6, 2006
 *
 */
public class TestFNFE extends TestCase{

    public TestFNFE(String method){
	super(method);
    }

    public void testFileNotFoundException(){
	
	out.println();
	File f = new File("BoggaWoooga.txt");
	try{
	    out.println( "Testing FileInputStream" );
	    FileInputStream fis = new FileInputStream(f);

	}
	catch(FileNotFoundException fnfe ){
	    
	    out.println("FileNotFoundException thrown as expected");
	    out.println("Do we have a File instance?");
	    out.println(fnfe.getFile());

	}

	try{
	    
	    out.println( "Testing RandomAccessFile" );
	    RandomAccessFile ras = new RandomAccessFile(f,"r");

	}
	catch(FileNotFoundException fnfe ){
	    
	    out.println("FileNotFoundException thrown as expected");
	    out.println("Do we have a File instance?");
	    out.println(fnfe.getFile());

	}

	out.println( "Testing creation via new constructor" );
	FileNotFoundException fnfe = new FileNotFoundException(f, "This is a test");
	out.println( "Do we have a file?" );
	out.println( fnfe.getFile() );
	out.println( "This test should produce a null File when getFile is called");
	FileNotFoundException fnfe2 = new FileNotFoundException();
	out.println( "Do we have a file?");
	out.println( fnfe2.getFile() );

    }


    public static void main(String[] args){

	TestFNFE test1 = new TestFNFE( "testFileNotFoundException" );
	TestRunner.run(test1);

    }


}


FIX FOR BUG NUMBER:
4614196

Comments
EVALUATION The real fix to this problem would require more than simply adding a constructor and method to FileNotFoundException. First, all of the places in the JDK where a FNFE is reported would need to be modified to include the file name, if available. Second, there are cases in which no file name is available, for example when dealing with file descriptors in FileReader, FileWriter, FileOutputStream, and FileInputStream. The detail string in any case will always be provided by the underlying OS and may or may not contain the file name. If there sufficient user scenarios which would significantly benefit from the introduction of this functionality, we would consider these changes, but they are non-trivial and we would never be able to always guarantee the presence of a file name.
07-02-2006

EVALUATION Contribution-forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=10784
07-01-2006

EVALUATION Seems reasonable. ###@###.### 2002-05-08
08-05-2002