JDK-4701462 : File.listFiles() with FileFilter and FilenameFilter give inconsistent results
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-06-13
  • Updated: 2005-11-30
  • Resolved: 2005-11-30
Related Reports
Duplicate :  
Description
Name: nt126004			Date: 06/12/2002


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

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

ADDITIONAL OPERATING SYSTEMS :
None tested


A DESCRIPTION OF THE PROBLEM :
It seems as if the methods:

java.io.File.listFiles(),
java.io.File.listFiles(FileFilter filter),
and
java.io.File.listFiles(FilenameFilter filter)

do not produce the same results on the root file (retrieved
with javax.swing.filechooser.FileSystemView.getRoots()) if
the two filter methods simply *always* return true.

Running the following sample code:

        File[] roots =
FileSystemView.getFileSystemView().getRoots();
        
        File[] rootsSubElems = roots[0].listFiles();
        System.out.println("roots sub dirs: ");
        for (int i = 0; i < rootsSubElems.length; i++)
        {
            System.out.println(rootsSubElems[i].toString());
        }
        
        rootsSubElems = roots[0].listFiles(new FileFilter() {
            public boolean accept(File path) { return true; }
        });
        System.out.println("roots sub dirs (with
FileFilter): ");
        for (int i = 0; i < rootsSubElems.length; i++)
        {
            System.out.println(rootsSubElems[i].toString());
        }
        
        rootsSubElems = roots[0].listFiles(new
FilenameFilter() {
            public boolean accept(File dir, String name) {
return true; }
        });
        System.out.println("roots sub dirs (with
FilenameFilter): ");
        for (int i = 0; i < rootsSubElems.length; i++)
        {
            System.out.println(rootsSubElems[i].toString());
        }

Produces this result:

roots sub dirs:
My Computer
My Network Places
C:\Documents and Settings\Administrator\Desktop\Downloads.lnk

roots sub dirs (with FileFilter):
C:\Documents and Settings\Administrator\Desktop\Downloads.lnk

roots sub dirs (with FilenameFilter):
C:\Documents and Settings\Administrator\Desktop\Downloads.lnk


For some reason, the methods that include the filters do not
get access to the "My Computer" and "My Network Places"
elements.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.  Run the sample code included in the Description on a
Win2K machine.
2.
3.

EXPECTED VERSUS ACTUAL BEHAVIOR :
I expected all three methods to return the same results, but
only the java.io.File.listFiles() method returned "My
Computer" and "My Network Places" in it's File array, the
other two methods didn't seem to find those elements.

This bug can be reproduced always.

---------- BEGIN SOURCE ----------


import java.io.*;
import javax.swing.filechooser.FileSystemView;

public class IOTest
{

    public static final void main(String args[])
    {
        File[] roots = FileSystemView.getFileSystemView().getRoots();
        
        File[] rootsSubElems = roots[0].listFiles();
        System.out.println("roots sub dirs: ");
        for (int i = 0; i < rootsSubElems.length; i++)
        {
            System.out.println(rootsSubElems[i].toString());
        }
        
        rootsSubElems = roots[0].listFiles(new FileFilter() {
            public boolean accept(File path) { return true; }
        });
        System.out.println("roots sub dirs (with FileFilter): ");
        for (int i = 0; i < rootsSubElems.length; i++)
        {
            System.out.println(rootsSubElems[i].toString());
        }
        
        rootsSubElems = roots[0].listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) { return true; }
        });
        System.out.println("roots sub dirs (with FilenameFilter): ");
        for (int i = 0; i < rootsSubElems.length; i++)
        {
            System.out.println(rootsSubElems[i].toString());
        }
    
    }
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
always use java.io.File.list() and weed out the elements you
don't want in the resulting array.
(Review ID: 153380) 
======================================================================

Comments
EVALUATION javax.swing.filechooser.FileSystemView.getRoots() returns a list of roots which are of type sun.awt.ShellFolder which extends File. When you call roots[0].listFiles(), you're really getting the listFiles() implemtation from an extension of ShellFolder. This uses the win32 shell APIs which includes virtual file system objects like "My Computer" and "My Network Places" which are not literal names on the file system. On the other hand, when you call the other listFiles implementations which take filters, you get the File implementation which uses POSIX file system APIs that do not include shell objects. The correct solution for consistency without introducing incompatibilities in File is for ShellFolder to add overrides for the following methods: public File[] listFiles(FilenameFilter filter); public File[] listFiles(FileFilter filter); Duplicate of swing bug 5086412.
30-11-2005