Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4722567

File and File{In,Out}putStream path directories inconsistent if user.dir is set on cmd line

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.4.0
    • core-libs
    • x86
    • windows_xp

      Name: nt126004 Date: 07/29/2002


      FULL PRODUCT VERSION :
      java version "1.4.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

      FULL OPERATING SYSTEM VERSION : Microsoft Windows XP
      [Version 5.1.2600]


      A DESCRIPTION OF THE PROBLEM :
      There are serious inconsistencies in the handling of non-
      absolute paths in the File and
      FileInputStream/FileOutputStream classes in Windows.

      The problem arises when the initial current directory (A)
      is different to the user.dir directory (B).

      new FileInputStream("xxx") always seems to open "xxx" in
      dir A.

      File f = new File("xxx") sometimes refers to dir A and
      sometimes to dir B:
              f.exists() and f.isDirectory() refer to dir A
      while
              f.getCanonicalPath() and f.getAbsolutePath()
      return dir B

      With user entered paths, to avoid confusion, I now have to
      use:
              File f = new File(xxx);
              f = new File(rv.getCanonicalPath());
              and always use new FileInputStream(f)
      to be sure of referring to the same file/dir all of the
      time.

      I suggest that File has a
              private String realPath;
      which is set to rv.getCanonicalPath() in the constructor,
      and is used for all file system accesses.

      And that FileInputStream/FileOutputStream (File file)
      constructor replaces
      String name = file.getPath();

      with
      String name = file.getCanonicalPath();


      These constructors will obviously now have to throw
      IOException as well.
      Or use getAbsolutePath() to avoid throwing this exception.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run source code from directory say D:\dirA which contains
      file test.txt with user.dir set to say D:\dirB which is
      empty
      eg: java -jar -Duser.dir="D:\dirB" d:\dirA\FilesBug.jar


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      I expect non-absolute paths passed to File and
      FileInputStream/FileOutputStream to consistently refer to
      the same file/dir.

      -----------------
      Windows File and FileInputStream/FileOutputStream path
      directories inconsistent

      user.dir=D:\dirB

      Before getAbsolutePath....
      .... f.exists: true
      .... f.getAbsolutePath(): D:\dirB\test.txt

      After getAbsolutePath.....
      .... f.exists: false

      dir.list() 0 test.txt
      dir.list() 1 FilesBug.class
      dir.list() 2 FilesBug.jar
      dir.list() 3 manifest.txt
      dir.list() 4 FilesBug.java
      dir.getAbsolutePath(): D:\dirB\.

      FileInputStream read: abcdefghijklmnopq


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // Run from directory say D:\dirA which contains file test.txt
      // with user.dir set to say D:\dirB which is empty
      //
      // java -jar -Duser.dir="D:\dirB" d:\dirA\FilesBug.jar

      import java.io.*;

      public final class FilesBug
      {

      public static void main(String[] args)
      {
      System.out.println("Windows File and FileInputStream/FileOutputStream
      path directories inconsistent");
      System.out.println();

      System.out.println("user.dir="+System.getProperty("user.dir"));
      System.out.println();

      // This test shows that a non-absolute file is in dir A but
      getAbsolutePath() returns dir B
      File f = new File("test.txt");
      System.out.println("Before getAbsolutePath....");
      System.out.println(".... f.exists: "+f.exists());
      System.out.println(".... f.getAbsolutePath(): "+f.getAbsolutePath());
      System.out.println();

      // Now check dir B
      f = new File(f.getAbsolutePath());
      System.out.println("After getAbsolutePath.....");
      System.out.println(".... f.exists: "+f.exists());
      System.out.println();

      // This test shows that a directory listing refers to dir A but /
      getAbsolutePath() returns dir B
      File dir = new File(".");
      if( dir.isDirectory())
      {
      String[] dirlist = dir.list();
      for( int i=0; i<dirlist.length; i++)
      System.out.println("dir.list() "+i+" "+dirlist[i]);
      System.out.println("dir.getAbsolutePath
      (): "+dir.getAbsolutePath());
      }
      else
      System.out.println("dir is not a directory");
      System.out.println();

      // This test shows that new FileInputStream("test.txt") refers to dir A
      try
      {
      DataInputStream ds = new DataInputStream(new FileInputStream
      ("test.txt"));
      String line = ds.readLine();
      System.out.println("FileInputStream read: "+line);
      }
      catch( Exception e)
      {
      System.out.println("FileInputStream failed: "+e);
      }
      }

      ////
      }
      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      With user entered paths, to avoid confusion, I now have to
      use:
              File f = new File(xxx);
              f = new File(rv.getCanonicalPath());
              and always use new FileInputStream(f)
      to be sure of referring to the same file/dir all of the
      time.
      (Review ID: 158686)
      ======================================================================

            iris Iris Clark
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: