I would like to take this one step back as I think that the getCanonicalFile() or getCanonicalPath() on an existing file should return the exact file name with the correct case as it is stored on the file system. At least that is what the JavaDoc says.
Can some one run this test program on OS X/HFS and post the results back? Before running this, make sure there is no directory named "Foo" in your working directory. import java.io.File; import java.io.IOException; public class FileCaseTest { public static void main(String[] args) throws IOException { File dir = new File("Foo"); boolean created = dir.mkdir(); System.out.println("Created directory " + dir + ": " + created); dir = new File("FOO"); System.out.println("Absolute Path: " + dir.getAbsoluteFile()); System.out.println("Canonical Path: " + dir.getCanonicalFile()); } } This is what I get on Windows: Created directory Foo: true Absolute Path: D:\linomasoftware\projects\test\FOO Canonical Path: D:\linomasoftware\projects\test\Foo On Linux: Created directory Foo: true Absolute Path: /home/inspiron/dev/eclipseworkspace/develop/FOO Canonical Path: /home/inspiron/dev/eclipseworkspace/develop/FOO The canonical path is still in all CAPS because there is no file with the name FOO exists. I would be curious to see what results we get back with the HFS file system in question. Regards, Sai Pullabhotla Phone: (402) 408-5753 Fax: (402) 408-6861 www.jMethods.com On Wed, Mar 4, 2009 at 4:13 PM, Niklas Gustavsson <nik...@protocol7.com>wrote: > On Mon, Mar 2, 2009 at 4:54 PM, Niklas Gustavsson <nik...@protocol7.com> > wrote: > > Let me whip up a prototype and we can test it on the available platforms. > > Alright, here's a prototype that I would much appreciate if all of you > would take the time to test. First of all, you need to set the > FILE_SYSTEM_TYPE to the correct value (this is only used for > verification in the tests). On case sensitive file systems (most of > the *nix file systems), this should be set to > FileSystemType.CaseSensitive. On NTFS it should be set to > CaseInsensitiveMissingAsTrue, and on case-insensitive HFS to > CaseInsensitiveMissingAsFalse. It would be very interesting to have > this code tested on other file systems. If you do, please report the > file system and the test results. > > /niklas > > package org.apache.ftpserver.filesystem.nativefs.impl; > > import java.io.File; > import java.io.FilenameFilter; > import java.io.IOException; > > import junit.framework.TestCase; > > public class FileEqualsTest extends TestCase { > > private enum FileSystemType { > CaseSensitive, > // non-existing files with different casing are equal > // e.g. NTFS > CaseInsensitiveMissingAsTrue, > // non-existing files with different casing are non-equal > // e.g. HFS > CaseInsensitiveMissingAsFalse > }; > > private static final FileSystemType FILE_SYSTEM_TYPE = > FileSystemType.CaseSensitive; > > private boolean isCaseSensitive() { > return FILE_SYSTEM_TYPE == FileSystemType.CaseSensitive; > } > > private boolean isCaseInsensitive() { > return FILE_SYSTEM_TYPE != FileSystemType.CaseSensitive; > } > > @Override > protected void setUp() throws Exception { > System.out.println("File system type: " + FILE_SYSTEM_TYPE); > super.setUp(); > } > > public void testSimple() throws IOException { > File f1 = new File("foo"); > assertTrue(f1.createNewFile()); > File f2 = new File("foo"); > > assertTrue(equals(f1, f2)); > } > > public void testNonExistingButSimple() { > File f1 = new File("foo"); > File f2 = new File("foo"); > > assertTrue(equals(f1, f2)); > } > > public void testDifferentCase() throws IOException { > File f1 = new File("foo"); > assertTrue(f1.createNewFile()); > File f2 = new File("FOO"); > > // if this succeeds, we have two different files > assertEquals(isCaseSensitive(), f2.createNewFile()); > > assertEquals(isCaseInsensitive(), equals(f1, f2)); > } > > public void testDifferentCaseNonExisting() throws IOException { > File f1 = new File("foo"); > File f2 = new File("FOO"); > > assertEquals(FILE_SYSTEM_TYPE == > FileSystemType.CaseInsensitiveMissingAsTrue, equals(f1, f2)); > } > > public void testSameNameDifferentParent() throws IOException { > File f1 = new File("foo"); > assertTrue(f1.createNewFile()); > File dir2 = new File("dir"); > assertTrue(dir2.mkdir()); > File f2 = new File(dir2, "foo"); > assertTrue(f2.createNewFile()); > > assertFalse(equals(f1, f2)); > } > > public boolean equals(final File f1, final File f2) { > if (f1 == null || f2 == null) { > return false; > } > > if (f1.equals(f2)) { > // file equals, valid on all file systems > return true; > } else { > boolean f1Exists = f1.exists(); > boolean f2Exists = f2.exists(); > > if (f1.getName().equalsIgnoreCase(f2.getName())) { > // same name, do both exist? > if (f1Exists && f2Exists) { > // both files exists, do they have the same parent? > > // TODO should we use canonical or absolute path? > File f1Parent = f1.getAbsoluteFile().getParentFile(); > File f2Parent = f2.getAbsoluteFile().getParentFile(); > > if (f1Parent != null && f2Parent != null) { > if (equals(f1Parent, f2Parent)) { > // okay, if we got here, the parents are the > same, > // the file names are the same and both files > exists > // let's check if there are multiple files > or only one in the parent > // with that name > > > // choosing either parent should be fine, > they are equal > String[] files = f1Parent > .list(new FilenameFilter() { > public boolean accept(File > dir, String name) { > return name.equalsIgnoreCase(f1 > .getName()); > } > }); > > if (files.length == 1) { > // exactly one file matched the name, > the files must be equal > return true; > } else if (files.length > 1) { > return false; > } else { > // no file matching, must be a bug somewhere > throw new RuntimeException("Should not > happen"); > } > } else { > // different parents, return false > return false; > } > } else if (f1Parent == null && f2Parent == null) { > // no parents, we can do nothing more and thus > have to return false > return false; > } else { > // different parents > return false; > } > } else if (!f1Exists && !f2Exists) { > // none of the file exists, we can only trust the > equals result (which by now must be false) > return false; > } else { > // only one of the files exists, return false > return false; > } > } else { > // file names not equal > return false; > } > } > } > > @Override > protected void tearDown() throws Exception { > new File("foo").delete(); > new File("FOO").delete(); > new File("dir/foo").delete(); > new File("dir").delete(); > } > > } >