Как получить текущий рабочий каталог в Java?

1029

Я хочу получить доступ к моему текущему рабочему каталогу, используя Java.

Мой код:

 String current = new java.io.File( "." ).getCanonicalPath();
        System.out.println("Current dir:"+current);
 String currentDir = System.getProperty("user.dir");
        System.out.println("Current dir using System:" +currentDir);

Вывод:

Current dir: C:\WINDOWS\system32
Current dir using System: C:\WINDOWS\system32

Мой вывод неверен, потому что диск C не является моим текущим каталогом.

Как получить текущий каталог?

Кази
источник
2
Вы можете вставить здесь то, что вы видите, когда вы выполняете cdкоманду в командной строке, когда вы выполняете это?
Nishant
3
Чего вы пытаетесь достичь, обращаясь к рабочему каталогу? Можно ли это сделать, используя вместо этого путь к классу? Например, если вам нужно прочитать текстовый файл в файловой системе, вы можете легко найти его, когда он находится в пути к классам.
Earldouglas
1
как? Не могли бы вы уточнить, пожалуйста?
C графика
1
Для некоторой информации о доступе к файлу на пути к классам, см stackoverflow.com/questions/1464291/...
downeyt
7
В целях отладки рабочий каталог может быть полезен, чтобы узнать, не кажется ли программе доступ к существующим файлам.
nsandersen

Ответы:

1152
public class JavaApplication {
  public static void main(String[] args) {
       System.out.println("Working Directory = " + System.getProperty("user.dir"));
  }
}

Это напечатает полный абсолютный путь от того места, где было инициализировано ваше приложение.


Из документации :

java.ioПакет разрешает относительные пути, используя текущий каталог пользователя. Текущий каталог представлен как системное свойство, то есть user.dirи является каталогом, из которого была вызвана JVM.

Ануй Патель
источник
25
@ubuntudroid: именно поэтому я упомянул, что он напечатает путь, с которого приложение инициализировалось. Полагаю, что поток запускает непосредственно jar / программу после запуска командной строки (которая находится в основном в C: \ WINDOWS \ system32). Я надеюсь, вы понимаете мою точку зрения. Предполагая, что вы проголосовали, оцените, что, по крайней мере, вы хотели оставить отзыв. :)
Anuj Patel
1
user.dir получит путь к папке, в которой запущен процесс. Чтобы узнать фактический путь к главной папке приложения, смотрите мой ответ ниже.
Питер Де Винтер
1
Я имею в виду «весь код, который полагается на него, чтобы найти текущий каталог, не работает». Не весь код в целом. (Я должен был
медлить,
13
@SubOptimal, если пользователь установил -Duser.dir, вероятно, он хочет запустить это в пользовательском рабочем каталоге.
barwnikk
5
@indyaah На самом деле этот ответ неверен, между пользовательским рабочим каталогом и текущим рабочим каталогом системного процесса есть небольшая разница; "user.dir" большую часть времени указывает на cwd процесса (java); но «user.dir» имеет другую семантику и не должен использоваться для получения cwd процесса Java; Кстати: есть больше свойств, доступных для процесса Java. docs.oracle.com/javase/tutorial/essential/environment/… просто для справки
comeGetSome
382

Смотрите: http://docs.oracle.com/javase/tutorial/essential/io/pathOps.html

Используя java.nio.file.Pathand java.nio.file.Paths, вы можете сделать следующее, чтобы показать, что Java считает вашим текущим путем. Это для 7 и далее, и использует NIO.

Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + s);

Это выводит, Current relative path is: /Users/george/NetBeansProjects/Tutorialsчто в моем случае, где я запустил класс. Построение путей относительным образом, без использования начального разделителя для указания того, что вы строите абсолютный путь, будет использовать этот относительный путь в качестве начальной точки.

geoO
источник
2
Первый не проверен, но второй фактически получит вашу домашнюю папку. Не текущий рабочий каталог, в котором запущено приложение.
Питер Де Винтер
12
Пожалуйста, не путайте домашний каталог пользователя ("user.home", / Users / george в вашем случае) и текущий рабочий каталог ("user.dir", который будет каталогом, из которого вы запустили JVM для вашего приложения). , поэтому может быть что-то вроде, например / Users / george / workspace / FooBarProject).
Дэвид
1
Я предпочитаю этот путь. Когда мне нужен родитель рабочего каталога, это не работает: Paths.get("").getParent()он дает null. Вместо этого работает: Paths.get("").toAbsolutePath().getParent().
Оле В.В.
235

Следующее работает на Java 7 и выше (см. Здесь для документации).

import java.nio.file.Paths;

Paths.get(".").toAbsolutePath().normalize().toString();
Дмитрий Беспалов
источник
11
Как это лучше, чем более портативный import java.io.File; File(".").getAbsolutePath()?
Евгений Сергеев
8
Когда вы говорите «портативный», вы имеете в виду, что он работает в Java 6 и более ранних версиях? Paths.get()может считаться лучше тем, что дает прямой доступ к более мощному Pathинтерфейсу.
Оле В.В.
8
Каково потенциальное преимущество использования .normalize()в этом контексте?
Оле В.В.
7
@ OleV.V. От Javadoc: ( нормализовать метод )Returns a path that is this path with redundant name elements eliminated.
Стефан
Уже нормализуется в этом случае.
Дж. М. Беккер
73

Это даст вам путь вашего текущего рабочего каталога:

Path path = FileSystems.getDefault().getPath(".");

И это даст вам путь к файлу с именем «Foo.txt» в рабочем каталоге:

Path path = FileSystems.getDefault().getPath("Foo.txt");

Редактировать: чтобы получить абсолютный путь к текущему каталогу:

Path path = FileSystems.getDefault().getPath(".").toAbsolutePath();

* Обновить * Чтобы получить текущий рабочий каталог:

Path path = FileSystems.getDefault().getPath("").toAbsolutePath();
отметка
источник
11
это просто возвращает "." для меня.
Джон Ktejik
3
Да, во многих системах это будет ссылка на рабочий каталог. Чтобы получить абсолютный путь, вы можете добавить еще один вызов методаPath path = FileSystems.getDefault().getPath(".").toAbsolutePath();
Mark
2
Вам не нужен foo.txt, просто вставьте пустую строку, чтобы получить каталог
Джон Ктеджик
1
В Windows (10) это просто дает мне Pathобъект, указывающий на файл, вызываемый .внутри текущего рабочего каталога . Используя пустую строку, а не "."работал для меня.
Kröw
36

Это решение для меня

File currentDir = new File("");
user2430452
источник
1
Это имеет побочные эффекты, когда вы используете такой объект File в качестве родителя другого файла: новый файл (новый файл (""), "subdir") не будет работать
должным образом
13
Чтобы исправить это, используйте new File("").getAbsoluteFile()вместо этого.
MRalwasser
4
Что бы это ни стоило, мне повезло больше с File (".").
Кешлам
Как определить относительный путь в Java Эта страница помогла мне. Также я предположил, что я должен использовать /при создании относительного пути. Я был неправ, не начинай с /. ../также работает для перехода в дерево каталогов.
Irrationalkilla
@keshlam Это дало мне файл в текущем каталоге под названием ..
Kröw
32

Я нашел это решение в комментариях, которое лучше других и более переносимо:

String cwd = new File("").getAbsolutePath();

Или даже

String cwd = Paths.get("").toAbsolutePath();
freedev
источник
Это точно так же, как ответ от comeGetSome и на самом деле Java <7 way
GoGoris
30

Что заставляет вас думать, что c: \ windows \ system32 не является вашим текущим каталогом? user.dirСвойство явно быть «текущий рабочий каталог пользователя».

Иными словами, если вы не запускаете Java из командной строки, c: \ windows \ system32, вероятно, является вашим CWD. То есть, если вы дважды щелкаете, чтобы запустить свою программу, CWD вряд ли будет каталогом, из которого вы дважды щелкнете.

Изменить : Похоже, что это верно только для старых версий Windows и / или Java.

Пол Уогланд
источник
2
Кажется, что это не так, по крайней мере, на моем компьютере с Windows 7, использующим Java 7., user.dirэто папка, в которой я дважды щелкнул файл jar.
Джолта
26

Использование CodeSource#getLocation().

Это прекрасно работает и в JAR-файлах. Вы можете получить CodeSource, ProtectionDomain#getCodeSource()а ProtectionDomainв свою очередь можно получить Class#getProtectionDomain().

public class Test {
    public static void main(String... args) throws Exception {
        URL location = Test.class.getProtectionDomain().getCodeSource().getLocation();
        System.out.println(location.getFile());
    }
}
Bigoloo
источник
2
Это возвращает местоположение файла JAR. Не то, что просили.
Маркиз Лорн
22
this.getClass().getClassLoader().getResource("").getPath()
Питер Де Винтер
источник
12
Выдает NPE, когда я запускаю свое приложение из файла JAR, дважды щелкнув по нему.
Мэтью Мудрый
2
Возвращается, ""если приложение выполняется из файла JAR или элемента CLASSPATH. Не то, что просили.
Маркиз Лорн
@ Zizouz212 getClass()- это объектный метод, поэтому в статическом контексте просто удаление thisне работает. Вы должны были бы явно обратиться к классу, в котором вы находитесь, делая MyClass.class.getClassLoader()......
Kröw
Тем не менее, он не вернет рабочий каталог ...
Ангел О'Сфера,
18

как правило, как объект File:

File getCwd() {
  return new File("").getAbsoluteFile();
}

Вы можете захотеть иметь полную квалифицированную строку, такую ​​как "D: / a / b / c", выполняя:

getCwd().getAbsolutePath()
comeGetSome
источник
1
Это хорошо работает в тестах Android, так как Android не включает java.nio.file.Files.
iamreptar
Кажется, не работает для меня в статическом контексте (новый File ("") генерирует исключение NullPointerException) ..?
nsandersen
2
@nsandersen вы, вероятно, использовали неправильный объект File: System.out.println (new java.io.File (""). getAbsolutePath ());
ComeGetSome
5

В Linux, когда вы запускаете файл jar из терминала , они оба возвращают одно и то же String: "/ home / CurrentUser" , независимо от того, где находится файл jar. Это зависит только от того, какой текущий каталог вы используете со своим терминалом, когда вы запускаете файл JAR.

Paths.get("").toAbsolutePath().toString();

System.getProperty("user.dir");

Если ваш Classс mainбудет называться MainClass, то попробуйте:

MainClass.class.getProtectionDomain().getCodeSource().getLocation().getFile();

Это будет возвращать Stringс абсолютным путем в банке файла.

Ян Повольный
источник
3
Что не то, о чем просили.
Маркиз Лорн
5

При использовании Windows user.dir возвращает каталог, как и ожидалось, но НЕ при запуске приложения с повышенными правами (запуск от имени администратора), в этом случае вы получаете C: \ WINDOWS \ system32

SijeDeHaan
источник
3

Я надеюсь, что вы хотите получить доступ к текущему каталогу, включая пакет, т. Е. Если ваша Java-программа включена c:\myApp\com\foo\src\service\MyTest.javaи вы хотите печатать до этого c:\myApp\com\foo\src\serviceмомента, вы можете попробовать следующий код:

String myCurrentDir = System.getProperty("user.dir")
            + File.separator
            + System.getProperty("sun.java.command")
                    .substring(0, System.getProperty("sun.java.command").lastIndexOf("."))
                    .replace(".", File.separator);
    System.out.println(myCurrentDir);

Примечание. Этот код тестируется только в Windows с Oracle JRE.

JSS
источник
6
Было бы плохой услугой, чтобы не понизить этот ответ. Пожалуйста, подумайте внимательно перед публикацией. Ваш код не работает, если все это не так: 1. JRE - это Oracle, иначе не будет системного свойства sun.java.command → NPE; 2. ОС - Windows (используйте File.separatorвзамен конструктор с несколькими аргументами File); 3. classpath указывается в командной строке, а «текущий каталог, включающий пакет» (??): a. указано первым, б. указано абсолютно, c. точно соответствует CWD (даже с учетом регистра Windows), и d. является потомком CWD
Майкл Шепер
Это относится к пунктам 1 и 2. Но если я что-то упустил, вы все еще полагаетесь на путь к классу, указанный в командной строке (т.е. не в переменной окружения), и на «текущий каталог, включающий пакет» ( признайся, я не очень понимаю, что ты имеешь в виду под этим) быть потомком именно первого элемента в classpath. И проблема соответствия случая остается. Извините, если мой комментарий не помог; Я пожертвовал ясностью, чтобы уложиться в лимит комментариев.
Майкл Шепер
@ Inversus, он только «отлично работает» в некоторых средах; вам просто посчастливилось проверить это в одном. Написание программного обеспечения, которое терпит неудачу в законных средах выполнения, не является хорошей практикой, даже если ваш набор тестовых сред недостаточно широк, чтобы включать их.
Чарльз Даффи
@CharlesDuffy Вы правы, это не очень хорошая практика. К счастью, это решение, «решающее мою конкретную проблему», не привело к его «отказу в законных средах выполнения». Фактически, это помогло мне решить такую ​​проблему и написать более надежный код, помимо решения очень специфической проблемы, с которой я столкнулся (которая была лишь отчасти связана с этим вопросом / ответом). Я думаю, мне просто повезло найти его.
Inversus
3

Стоит упомянуть, что это только проверено, Windowsно я думаю, что оно отлично работает на других операционных системах [ Linux,MacOs,Solaris] :).


У меня было 2 .jar файла в одном каталоге. Я хотел из одного .jarфайла запустить другой .jarфайл, который находится в том же каталоге.

Проблема в том, что при запуске его из cmdтекущего каталога есть system32.


Предупреждение!

  • Приведенное ниже, похоже, работает очень хорошо во всех тестах, которые я провел, даже с именем папки, ;][[;'57f2g34g87-8+9-09!2#@!$%^^&()или ()%&$%^@# он работает хорошо.
  • Я использую ProcessBuilderс ниже следующим:

🍂 ..

//The class from which i called this was the class `Main`
String path = getBasePathForClass(Main.class);
String applicationPath=  new File(path + "application.jar").getAbsolutePath();


System.out.println("Directory Path is : "+applicationPath);

//Your know try catch here
//Mention that sometimes it doesn't work for example with folder `;][[;'57f2g34g87-8+9-09!2#@!$%^^&()` 
ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath);
builder.redirectErrorStream(true);
Process process = builder.start();

//...code

🍂 getBasePathForClass(Class<?> classs):

    /**
     * Returns the absolute path of the current directory in which the given
     * class
     * file is.
     * 
     * @param classs
     * @return The absolute path of the current directory in which the class
     *         file is.
     * @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user]
     */
    public static final String getBasePathForClass(Class<?> classs) {

        // Local variables
        File file;
        String basePath = "";
        boolean failed = false;

        // Let's give a first try
        try {
            file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());

            if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
                basePath = file.getParent();
            } else {
                basePath = file.getPath();
            }
        } catch (URISyntaxException ex) {
            failed = true;
            Logger.getLogger(classs.getName()).log(Level.WARNING,
                    "Cannot firgue out base path for class with way (1): ", ex);
        }

        // The above failed?
        if (failed) {
            try {
                file = new File(classs.getClassLoader().getResource("").toURI().getPath());
                basePath = file.getAbsolutePath();

                // the below is for testing purposes...
                // starts with File.separator?
                // String l = local.replaceFirst("[" + File.separator +
                // "/\\\\]", "")
            } catch (URISyntaxException ex) {
                Logger.getLogger(classs.getName()).log(Level.WARNING,
                        "Cannot firgue out base path for class with way (2): ", ex);
            }
        }

        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbeans
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    }
GOXR3PLUS
источник
Это возвращает местоположение файла JAR. Не то, что просили.
Маркиз Лорн
@EJP Расположение файла .jar не является текущим рабочим каталогом Java-программы?
GOXR3PLUS
2

Текущий рабочий каталог определяется по-разному в разных реализациях Java. Для определенной версии до Java 7 не было последовательного способа получить рабочий каталог. Вы можете обойти это, запустив Java-файл -Dи определив переменную для хранения информации.

Что-то вроде

java -D com.mycompany.workingDir="%0"

Это не совсем верно, но вы поняли идею. Тогда System.getProperty("com.mycompany.workingDir")...

MJB
источник
6
Не имеет отношения к вопросу.
Питер Де Винтер
1
Это имеет значение для Java - это место на диске, к которому относятся файлы, которые вы открываете с относительными путями.
Роб I
2
Да, это имеет значение. Мои слова были выбраны плохо. Но вы упускаете суть - до Java 7 не было способа узнать текущий рабочий каталог, и разные реализации устанавливали их ... по-разному ...
MJB
1

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

public static final String getBasePathForClass(Class<?> clazz) {
    File file;
    try {
        String basePath = null;
        file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
            basePath = file.getParent();
        } else {
            basePath = file.getPath();
        }
        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbean
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    } catch (URISyntaxException e) {
        throw new RuntimeException("Cannot firgue out base path for class: " + clazz.getName());
    }
}

Чтобы использовать, везде, где вы хотите получить базовый путь для чтения файла, вы можете передать свой якорный класс вышеуказанному методу, результат может быть тем, что вам нужно: D

Лучший,

bachden
источник
2
Это возвращает местоположение файла JAR. Не то, что просили.
Маркиз Лорн
@ user207421 да, я знаю, что этот ответ не является верным ответом на вопрос, но в большинстве случаев все хотят получить «каталог, в котором находятся фляги», а не «рабочий каталог командной строки».
Бачден
0

Ни один из ответов, опубликованных здесь, не работал для меня. Вот что сработало:

java.nio.file.Paths.get(
  getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
);

Изменить: окончательная версия в моем коде:

URL myURL = getClass().getProtectionDomain().getCodeSource().getLocation();
java.net.URI myURI = null;
try {
    myURI = myURL.toURI();
} catch (URISyntaxException e1) 
{}
return java.nio.file.Paths.get(myURI).toFile().toString()
VenerableAgents
источник
Это возвращает местоположение файла JAR. Не то, что просили.
Маркиз Лорн
0

Это моя серебряная пуля, когда в нее впадает момент смятения. (Назовите это первым делом в главном). Может быть, например, JVM добавлена ​​в IDE для другой версии. Эта статическая функция ищет PID текущего процесса и открывает VisualVM для этого pid. Путаница тут же прекращается, потому что вы хотите всего этого, и вы получите это ...

  public static void callJVisualVM() {
    System.out.println("USER:DIR!:" + System.getProperty("user.dir"));
    //next search current jdk/jre
    String jre_root = null;
    String start = "vir";
    try {
        java.lang.management.RuntimeMXBean runtime =
                java.lang.management.ManagementFactory.getRuntimeMXBean();
        String jvmName = runtime.getName();
        System.out.println("JVM Name = " + jvmName);
        long pid = Long.valueOf(jvmName.split("@")[0]);
        System.out.println("JVM PID  = " + pid);
        Runtime thisRun = Runtime.getRuntime();
        jre_root = System.getProperty("java.home");
        System.out.println("jre_root:" + jre_root);
        start = jre_root.concat("\\..\\bin\\jvisualvm.exe " + "--openpid " + pid);
        thisRun.exec(start);
    } catch (Exception e) {
        System.getProperties().list(System.out);
        e.printStackTrace();
    }
}
Kurskinen
источник
-6

System.getProperty("java.class.path")

Марко Стойкович
источник
-7

это имя текущего каталога

String path="/home/prasad/Desktop/folderName";
File folder = new File(path);
String folderName=folder.getAbsoluteFile().getName();

это текущий путь к каталогу

String path=folder.getPath();
Прасад Де Сильва
источник
1
ОП требовал текущего рабочего каталога, из которого запускалось приложение.
Лейф Грюнвольдт
Это ваш домашний каталог, а не текущий рабочий каталог кого-либо, кроме, может быть, вашего. Не то, что просили.
Маркиз Лорн