Подтвердить что ты не робот

Java не может найти файл при работе через Eclipse

Когда я запускаю приложение Java, которое следует читать из файла в Eclipse, я получаю java.io.FileNotFoundException, хотя файл находится в правильном каталоге. Я могу легко скомпилировать и запустить приложение из командной строки; проблема возникает только в Eclipse, с несколькими проектами и приложениями. Есть ли параметр, который мне нужно изменить в конфигурациях запуска или построить пути, чтобы найти его правильно?

4b9b3361

Ответ 1

Проблема, скорее всего, в том, что ваше приложение использует относительный путь. Как говорит @BalusC, относительные пути могут быть проблематичными. Но ИМО, он идет слишком далеко, когда говорит: "[y] ou должен никогда использовать относительные пути в java.io stuff".

Когда приложение открывает файл, используя (например) конструктор FileInputStream(File), относительные пути уничтожаются относительно "текущего каталога" в процессе, описанном ниже в javadoc для File.getAbsolutePath().

[...] В противном случае это имя пути будет разрешено зависящим от системы образом. В системах UNIX относительный путь становится абсолютным, разрешая его против текущего каталога пользователя. В системах Microsoft Windows относительный путь становится абсолютным, разрешая его против текущего каталога диска, названного именем пути, если таковой имеется; если нет, он разрешен в отношении текущего каталога пользователя.

Итак, мы сразу видим, что понятие "текущий каталог" имеет разные нюансы на платформах Windows и UNIX. Вторая проблема заключается в том, что в чистой Java вы не можете окончательно узнать, что такое текущий каталог, и вы, конечно же, не можете изменить его для текущей JVM с использованием чистой Java. (Когда запускается JVM, системное свойство "user.dir" устанавливается в текущую директорию, но нет ничего, что останавливало бы приложение от изменения свойства, поэтому вы не можете полностью полагаться на него. Кроме того, изменение "user.dir" изменяется только путь пустого пути, а не относительные пути вообще.)

Итак, что вы должны сделать по этому поводу?

  • Один из вариантов - использовать абсолютные пути для обращения к файлам. Это достоверно (почти) во всех случаях, но использование абсолютных путей может быть проблематичным, если пользователь должен ввести имя пути или если вам необходимо избегать жестких (или настроенных) абсолютных путей пути.

  • Второй вариант - использовать относительные пути пути classpath и находить файлы относительно каталога установки приложения. Это работает, если это то, что вам нужно сделать, но представляет проблему, если вам нужно передать метод File в какой-либо библиотечный метод. Это также не помогает, если вы пытаетесь найти настройки пользовательского приложения. (В общем, внесение пользовательских настроек в каталог установки является ошибкой...)

  • Третий вариант - указать файл относительно некоторого абсолютного каталога, который вы получаете из другого места; например new File(System.getProperty("home.dir"), "foo/bar");.

  • Последняя опция - использовать относительные пути, и предположить, что пользователь знает, что такое текущий каталог. Для многих приложений, которые пользователь запускает из командной строки, это правильное решение.

В частном случае Eclipse существует простое решение. Перейдите в "конфигурацию запуска", которую вы используете для запуска приложения, откройте вкладку "Аргументы" и нажмите переключатель "Другой". Затем введите абсолютное имя пути как рабочий каталог для запущенного приложения. Когда запускается дочерний JVM, в качестве текущего каталога будет указан указанный рабочий каталог.

Ответ 2

Другим вариантом является просто выяснить, какой каталог указывает "текущий путь" в вашей среде - что бы это ни было. Как только вы выясните, вы можете выбрать свое решение оттуда. Возможно, это использовать соответствующий относительный путь к вашему местоположению файла или перемещение файла.

    File testFile = new File("");
    String currentPath = testFile.getAbsolutePath();
    System.out.println("current path is: " + currentPath);

Ответ 3

Когда вы создаете Java-приложение по умолчанию в Eclipse, вы получаете эту структуру каталогов:

./ProjectName/ - корневой каталог
./ProjectName/bin/ - каталог вывода, содержащий файлы .class
./ProjectName/src/ - исходный каталог, содержащий .java файлы

Если ваше приложение запрашивает "./data.txt", он будет искать его по отношению к корневому каталогу. Это "рабочий каталог" и может быть настроен на вкладке "Параметры" в соответствии с ответом Мартина выше.

Вы говорите, что это работает из командной строки? Вероятно, это связано с тем, что вы работаете в папке bin или src при запуске java-двоичного файла. Рабочий каталог в этом случае - это тот каталог, в котором сейчас находится командная строка. Если, например, вы заходите в каталог /src/, скажем javac *.java, затем запустите файлы там, он будет искать "./data.txt" в каталоге /src/. Если вы заходите в каталог/bin/и запускаете свое приложение оттуда, он будет искать файл относительно каталога/bin/.

Ответ 4

Вы должны никогда использовать относительные пути в материалах java.io. Путь будет зависеть от текущего рабочего каталога, который зависит от способа запуска приложения и, таким образом, не является таким же во всех средах. Это неконтролируемо изнутри приложения Java. Проблемы с переносимостью! Всегда используйте абсолютные пути. Так, например, c:/path/to/file.ext или /path/to/file.ext (с ведущей косой чертой) для UNIX и супругов (или даже Windows, когда буква диска не имеет значения).

Всякий раз, когда вы хотите отправить некоторые файлы вместе с вашим приложением, обычной практикой является их размещение в classpath. Таким образом вы можете просто использовать ClassLoader#getResource(), чтобы получить его местоположение. Он возвращает URL. Вы можете использовать URL#toURI() или URL#getPath() и передать его конструктору java.io.File, а затем использовать его обычным способом.

В проекте Eclipse папка src (где находится ваш источник Java) является в основном корнем пути к классам. Далее он, конечно, также охватывает все другие проекты и (внешние) папки, которые берутся в проекте "Путь сборки".

Предполагая, что вы поместили конкретный файл в корень пути к классам:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("file.ext");
File file = new File(url.getPath());
FileInputStream input = new FileInputStream(file);
// ...

Вы можете даже использовать ClassLoader#getResourceAsStream(), чтобы получить InputStream:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("file.ext");
// ...

Если он помещен внутри пакета, вы можете просто использовать обычные пути:

URL url = classLoader.getResource("com/example/file.ext");
// ...

или

InputStream input = classLoader.getResourceAsStream("com/example/file.ext");
// ...

Ответ 5

У меня была аналогичная проблема, я поместил файлы в папку cobolcopybooks внутри папки src и попытался получить к ним доступ в моем проекте, используя classloader.getResource( "cobolcopybooks/demostud.cob" ) но я получал исключение из null-указателя, я несколько раз пытался его очистить и построить рабочие пространства после нескольких неудачных попыток, я понял, что я не обновлял проект, чтобы файлы могли создаваться вместе с проектом. i.e эти файлы должны быть видны вместе с другими файлами классов, так как во время выполнения корневой каталог будет bin-каталогом и он ищет там те файлы.

Ответ 6

Предполагая, что пользователь не вводит полный путь к файлу в файл и введите что-то вроде "myfilenameonly". File file = new File(".", args[0]) необходимо в этом случае найдите файл (обращая внимание на первый переданный аргумент).

Все платформы: File.getParent() не возвращает родительский каталог, он должен возвращать ".." или имя родительского каталога в файловой системе конкретным способом.

Если вы создадите файл "myfilenameonly" без указания полного пути в каталог, где он находится, File.getParent(), например, вернет null.

Смотрите далее: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=1228537