Вопрос по eclipse, java, exception, filereader, file – Java не может найти файл при запуске через Eclipse

19

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

не видя ваш код, мы не можем сказать вам, что может происходить Kevin Day

Ваш Ответ

6   ответов
1

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

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

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

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

8

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

    File testFile = new File("");
    String currentPath = testFile.getAbsolutePath();
    System.out.println("current path is: " + currentPath);
Это не идеально для доставки кода, но он определенно полезен в качестве кода отладки, чтобы увидеть, что думает ваше приложение. Steve
29

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

Когда приложение открывает файл с помощью (например)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

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

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

В вашем проекте Eclipsesrc Папка (куда отправляется ваш 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");
// ...
@Stephen: что, таким образом, не так в первоначальном вопросе :) BalusC
@Stephen: Конечно, это возможно, вам придется только хлопотить с относительными путями, но это не рекомендуется. Использование преимуществ classpath делает его более надежным. BalusC
это зависит от того, что делает приложение. Например, если он манипулирует файлами, предоставленными пользователем, подход с использованием classpath не имеет смысла. Stephen C
приложение командной строки без графического интерфейса может быть разумно спроектировано для использования относительных имен путей. Предупреждение состоит в том, что пользователь должен понимать концепцию «текущего каталога», а программист должен понимать, как это соотносится с поведением библиотек Java IO. Stephen C
ноЯВЛЯЕТСЯ случай в контексте вашего ответа -"Вам следуетникогда использовать относительные пути в java.io. " Stephen C
7

вы получаете следующую структуру каталогов:

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

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

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

Спасибо за вашу помощь. Текстовые файлы, которые мне нужны, существуют в каталоге / bin /, так что это не проблема. Я поиграюсь с относительными путями и посмотрю, что я могу получить. derekerdmann
2

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

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