Как передать произвольный путь к файлу в Java-программу
Что проверяют
Знаете ли вы, откуда программа получает настройки при запуске и как надёжно превратить строку в путь. Следом часто спрашивают, относительно чего разрешается относительный путь и что изменится, если программа упакована в jar или запущена в контейнере.
Как отвечать
Назовите основные каналы:
- аргументы командной строки:
java -jar app.jar /data/input.csv, путь приходит вString[] argsметодаmain. Когда опций много, берут библиотеку разбора аргументов, например picocli; - системное свойство:
java -Dinput.file=/data/input.csv -jar app.jar, читается черезSystem.getProperty("input.file"); - переменная окружения:
System.getenv("INPUT_FILE"), удобно в Docker и Kubernetes; - конфигурация фреймворка: в Spring Boot свойство задаётся аргументом
--input.file=...или переменнойINPUT_FILEи читается через@ConfigurationPropertiesили@Value.
Дальше строка превращается в Path: Path.of(args[0]) (Java 11+) или Paths.get. Относительный путь разрешается от рабочего каталога процесса (user.dir), а не от места, где лежит jar, поэтому полезно залогировать path.toAbsolutePath().normalize().
Читать лучше через NIO: Files.newBufferedReader(path, StandardCharsets.UTF_8) или Files.lines(path) в try-with-resources. Предварительный Files.exists не спасает от гонки, надёжнее сразу открыть файл и обработать NoSuchFileException и AccessDeniedException с понятным сообщением.
Где спотыкаются
Ждут, что Java раскроет ~ или $HOME. Это делает оболочка, и только для аргумента без кавычек. Из переменной окружения или конфига ~/data придёт буквально и не найдётся. Туда же пути с пробелами: без кавычек при запуске в args придут два аргумента.
Путают файл на диске и ресурс внутри jar. Ресурс читается через getClass().getResourceAsStream(...), а new File(...) на него после упаковки не работает, хотя в IDE всё проходило.
Не думают о безопасности, когда путь приходит от пользователя через веб. Путь нужно нормализовать и проверить resolved.startsWith(baseDir), иначе ../../etc/passwd откроет чужой файл.