Java: File.exists () несоответствия при установке “user.dir”

JRE 6, на Windows XP.

Instanciating два объекта Файла с различными конструкторами приводит к непоследовательным результатам в File.exists() метод.

Правовая оговорка: код ниже является кратким обзором, не фактическим кодом. Я не полагаю, что это - проблема File.separator вообще. Я сначала попросил получать ранние реакции, в случае, если я пропустил хорошо понятую проблему. Это теперь кажется тем сбросом user.dir системное свойство является одной из причин к этой проблеме. Код ниже теперь восстанавливаем и применим, как. Вы можете скопировать/вставить класс Java и пробовать его, это должно последовательно вести себя с тем, что я перечислил как результаты.

Установка:

Создайте архитектуру папки C:\toto\tmp\sub.

Запустите следующий класс из любой папки, которая не содержит a tmp/sub архитектура подпапки.

Код:

public class TestFileExists {

    public static void main(String[] args) {

        System.setProperty("user.dir", "C:\\toto\\");

        File root = new File("tmp");

        File sub_a = new File(root, "sub");

        File sub_b = new File(root.getAbsolutePath()+"/sub");

        System.out.println("sub_a path ? "+sub_a.getAbsolutePath());
        System.out.println("sub_a exists ? "+sub_a.exists());
        System.out.println("sub_b path ? "+sub_b.getAbsolutePath());
        System.out.println("sub_b exists ? "+sub_b.exists());
        System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));
        System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));

    }

}

Результат:

sub_a path ? C:\toto\tmp\sub
sub_a exists ? false
sub_b path ? C:\toto\tmp\sub
sub_b exists ? true
Path equals ? true
Obj equals ? false

Я не понимаю строку sub_a exists ? false, и результат не последователен с машины на машину, ни с корневым муравьем начального тракта результат теперь согласовывается с с машины на машину.

Теперь, если Вы повторно выполняете класс путем вызова Java из командной строки из папки, которая действительно содержит a tmp/sub архитектура подпапки (как то, если Вы называете его от D:\, наличие D:\tmp\sub), Вы получите ожидаемый:

sub_a path ? C:\toto\tmp\sub
sub_a exists ? true
sub_b path ? C:\toto\tmp\sub
sub_b exists ? true
Path equals ? true
Obj equals ? false

Но существование sub_a ясно положительная ложь, потому что она проверяет существование другой папки, чем та, описанная getAbsolutePath().

Таким образом, я сильно подозреваю это File.exists() зависит от фактического пути выполнения Java, и то существование файла не согласовывается с полным путем, и exists() использование другой путь, чем "user.dir" системное свойство для проверки файловой системы.

Какая-либо идея, куда эта проблема могла возникнуть из?

9
задан glmxndr 17 February 2010 в 03:31
поделиться

7 ответов

Установка user.dir не поддерживается. Его следует рассматривать как свойство только для чтения.

Например, оценка Bug 4117557 в Sun Bug Parade содержит следующий текст:

"user.dir", который инициализируется во время запуска jvm, должен использоваться как информативное/нечитаемое системное свойство, попробуйте настроить его через командную строку -Duser.dir=xyz приведет к зависимому от реализации/неопределенному поведению.

Хотя в этом тексте речь идет об установке в командной строке, установка через setProperty(), скорее всего, также не определена.

Когда вы сможете воспроизвести проблему без установки user.dir вручную, значит, вы нашли настоящую проблему.

10
ответ дан 2 November 2019 в 23:07
поделиться

В этой строке:

File sub_b = new File(root.getAbsolutePath()+"/sub");

Вы должны использовать константу File.separator (в зависимости от базового system), а не жестко запрограммированную косую черту.

0
ответ дан 2 November 2019 в 23:07
поделиться

Я думаю, это разделитель каталогов, поскольку в Windows обычно используется обратная косая черта «\», а в Linux - обычная косая черта «/».

Попробуйте изменить строку на:

File sub_b = new File(root.getAbsolutePath() + System.getProperty("file.separator") + "sub");
0
ответ дан 2 November 2019 в 23:07
поделиться

Эти результаты должны быть детерминированными через машины. Позвольте мне разбить это по строкам:

System.out.println("sub_a exists ? "+sub_a.exists());

Здесь вы спрашиваете, действительно ли этот файл существует в файловой системе. Это всегда должно возвращать то же самое, если файл существует.

System.out.println("sub_b exists ? "+sub_b.exists());

То же самое. Вы проверяете, существует ли этот файл на самом деле.

System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));

Здесь вы видите, совпадает ли AbsolutePath .

System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));

И здесь вы выполняете сравнение объектов с помощью .equals (), который под капотом вызывает класс FileSystem для выполнения compare () двух объектов path объектов, а не их ] AbsolutePath .

Вероятно, что разделитель файлов неверен. Попробуйте заменить File.separator в конструкции sub_b, например:

File sub_b = new File(root.getAbsolutePath()+File.separator+"sub");
0
ответ дан 2 November 2019 в 23:07
поделиться

Это может быть проблема с разделителем файлов. В Windows стандартным разделителем файлов является обратная косая черта ( \ ). Когда вы создаете sub_b , вы создаете имя пути (как String ), которое содержит как косую черту, так и обратную косую черту. Система может немного запутаться в этом.

0
ответ дан 2 November 2019 в 23:07
поделиться

Добавьте следующие строки к вашему тесту:

System.out.println("sub_a = " + sub_a);
System.out.println("sub_b = " + sub_b);

Выводы:

1) sub_a - относительный путь, а sub_b - абсолютный.

2) exists() не использует абсолютный путь

3) установка переменной окружения user.dir не изменяет текущий каталог пользователя, используемый exists()

4) getAbsolutePath использует переменную user.dir вместо реального текущего каталога пользователя! По крайней мере, для Windows (см. Win32FileSystem.getuserPath). В этом и заключается проблема! (Баг?)

2
ответ дан 2 November 2019 в 23:07
поделиться

Файл может представлять собой абстрактный путь. Создание файла для tmp и одного из абсолютного пути к tmp не будут равны объектам File , хотя их абсолютные пути равны.

Я не совсем уверен в сценарии, при котором sub_a не будет существовать, а sub_b будет, но я сомневаюсь, что это проблема разделителя. Я подозреваю, что это как-то связано с этим утверждением из javadoc for File (File, String) :

каждая строка имени пути преобразуется в абстрактный путь, а абстрактное имя пути дочернего элемента сопоставляется с родительским.

Я не знаю ситуации в файловых системах на основе Unix, где изнутри / full / path / to , ./ tmp / sub будет существовать, но / полный / путь / к / tmp не будет.

Если проблема одинакова для разных систем, ее можно понять более четко, выгрузив больше состояний каждого объекта File , а не просто распечатав сравнения.

1
ответ дан 2 November 2019 в 23:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: