Изменение текущего рабочего каталога в Java?



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



У меня есть кусок кода, который открывает файл, используя жестко относительный путь к файлу из каталога это нормально начал, а я просто хочу быть в состоянии использовать этот код из другой программы Java без запуска его в частности справочник. Похоже, вы просто должны быть в состоянии позвонить System.setProperty( "user.dir", "/path/to/dir" ), но насколько я могу понять, вызов этой линии просто молча терпит неудачу и ничего не делает.



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

557   13  

13 ответов:

нет надежного способа сделать это в чистой Java. Установка user.dir собственность через System.setProperty() или java -Duser.dir=... похоже, влияет на последующие творения Files, но не например,FileOutputStreams.

The File(String parent, String child) конструктор может помочь, если вы создадите свой путь к каталогу отдельно от пути к файлу, что позволит упростить обмен.

альтернативой является настройка скрипта для запуска Java из другого каталога или использование собственного кода JNI как было предложено ниже.

соответствующая ошибка Солнца был закрыт в 2008 году как "не исправить".

Если вы запустите свою устаревшую программу с ProcessBuilder, вы сможете указать его рабочий каталог.

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

import java.io.*;

public class FileUtils
{
    public static boolean setCurrentDirectory(String directory_name)
    {
        boolean result = false;  // Boolean indicating whether directory was set
        File    directory;       // Desired current working directory

        directory = new File(directory_name).getAbsoluteFile();
        if (directory.exists() || directory.mkdirs())
        {
            result = (System.setProperty("user.dir", directory.getAbsolutePath()) != null);
        }

        return result;
    }

    public static PrintWriter openOutputFile(String file_name)
    {
        PrintWriter output = null;  // File to open for writing

        try
        {
            output = new PrintWriter(new File(file_name).getAbsoluteFile());
        }
        catch (Exception exception) {}

        return output;
    }

    public static void main(String[] args) throws Exception
    {
        FileUtils.openOutputFile("DefaultDirectoryFile.txt");
        FileUtils.setCurrentDirectory("NewCurrentDirectory");
        FileUtils.openOutputFile("CurrentDirectoryFile.txt");
    }
}

можно изменить PWD, используя JNA / JNI для вызова libc. У парней JRuby есть удобная библиотека java для совершения вызовов POSIX под названием jna-posix здесь информация maven

вы можете увидеть пример его использования здесь (код Clojure, извините). Посмотрите на функцию chdirToRoot

Если я правильно понимаю, программа Java начинается с скопировать из текущих переменных окружения. Любые изменения через System.setProperty(String, String) изменяют копию, а не исходные переменные среды. Не то, чтобы это дает полную причину, почему Солнце выбрало такое поведение, но, возможно, оно проливает немного света...

Как уже упоминалось, вы не можете изменить CWD JVM, но если вы должны были запустить другой процесс с помощью среды выполнения.exec () можно использовать перегруженный метод, который позволяет указать рабочий каталог. Это не совсем для запуска вашей Java-программы в другом каталоге, но во многих случаях, когда нужно запустить другую программу, например скрипт Perl, вы можете указать рабочий каталог этого скрипта, оставив рабочий каталог JVM без изменений.

посмотреть во время выполнения.старпома документации

в частности,

public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException

здесь dir это рабочий каталог для запуска подпроцесса в

рабочий каталог-это функция операционной системы (устанавливается при запуске процесса). Почему бы вам просто не передать свое собственное системное свойство (-Dsomeprop=/my/path) и использовать это в коде в качестве родителя вашего файла:

File f = new File ( System.getProperty("someprop"), myFilename)

умнее / проще сделать здесь, чтобы просто изменить свой код так, чтобы вместо открытия файла предполагая, что он существует в текущем рабочем каталоге (я предполагаю, что вы делаете что-то вроде new File("blah.txt"), просто построить путь к файлу самостоятельно.

пусть пользователь проходит в базовую директорию, читает ее из файла конфигурации, возвращается к user.dir если другие свойства не могут быть найдены, и т. д. Но это намного проще улучшить логику в вашей программе, чем изменить как работают переменные среды.

Я пытался вызвать

String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());

Это, кажется, работает. Но

File myFile = new File("localpath.ext"); InputStream openit = new FileInputStream(myFile);

бросает a FileNotFoundException хотя

myFile.getAbsolutePath()

показывает правильный путь. У меня есть читать это. Я думаю, что проблема заключается в следующем:

  • Java знает текущий каталог с новой настройкой.
  • но обработка файлов осуществляется операционной системой. Он не знает новый набор текущего каталога, к сожалению.

решение может быть:

File myFile = new File(System.getPropety("user.dir"), "localpath.ext");

он создает объект file как абсолютный с текущим каталогом, который известен JVM. Но этот код должен существовать в используемом классе, он нуждается в изменении повторно используемых кодов.

~~~~JcHartmut

можно использовать

новый файл("относительный/путь").getAbsoluteFile()

после

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

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

Если вы запускаете свои команды в оболочке, вы можете написать что-то вроде "java-cp" и добавить любые каталоги, которые вы хотите разделить ":" если java не найдет что-то в одном каталоге, он попытается найти их в других каталогах, вот что я делаю.

Использовать Значения По Умолчанию Пользователя

private FileSystemView fileSystemView;
fileSystemView = FileSystemView.getFileSystemView();
currentDirectory = new File(".");
//listing currentDirectory
File[] filesAndDirs = fileSystemView.getFiles(currentDirectory, false);
fileList = new ArrayList<File>();
dirList = new ArrayList<File>();
for (File file : filesAndDirs) {
if (file.isDirectory())
    dirList.add(file);
else
    fileList.add(file);
}
Collections.sort(dirList);
if (!fileSystemView.isFileSystemRoot(currentDirectory))
    dirList.add(0, new File(".."));
Collections.sort(fileList);
//change
currentDirectory = fileSystemView.getParentDirectory(currentDirectory);

Comments

    Ничего не найдено.