Java에서 현재 작업 디렉토리를 변경 하시겠습니까?


169

Java 프로그램 내에서 현재 작업 디렉토리를 어떻게 변경합니까? 내가 당신이 단순히 할 수 없다는 문제 주장에 대해 찾을 수 있었던 모든 것이지만, 나는 그것이 실제로 사실이라고 믿을 수 없습니다.

일반적으로 시작되는 디렉토리에서 하드 코딩 된 상대 파일 경로를 사용하여 파일을 여는 코드 조각이 있으며 내부에서 시작할 필요없이 다른 Java 프로그램에서 해당 코드를 사용할 수 있기를 원합니다. 특정 디렉토리. 그것은 당신이 전화 할 수 있어야하는 것처럼 보이지만 System.setProperty( "user.dir", "/path/to/dir" ), 내가 알아낼 수있는 한 그 줄을 전화하는 것은 조용히 실패하고 아무것도하지 않습니다.

Java가 현재 작업 디렉토리 를 거나 상대 파일 경로를 사용하여 파일을 열 수 없다는 사실이 아니라면 Java 가이 작업을 수행 할 수 없었는지 이해 합니다 ....


1
정보를 얻고 사용하는 것은 정보를 변경하는 것과 다릅니다. 예를 들어 Windows에서는 환경 변수를 쉽게 얻을 수 있지만 시스템 전체에서 변경하기가 더 어렵습니다.
PhiLho

1
평가 섹션의 bugs.java.com/bugdatabase/view_bug.do?bug_id=4045688 상태는 "그 이후로 더 이상 고객이 나오지 않았거나 다른 방법으로 확인되지 않았습니다. ..."이며 2018 년 현재 약 175.000 명입니다. 이 질문에 대한 의견 :-(
Wolfgang Fahl

답변:


146

순수한 Java에서는이를 수행 할 수있는 확실한 방법이 없습니다. 설정 user.dir을 통해 속성을 System.setProperty()또는 java -Duser.dir=...후속 작품에 영향을 미치는 것으로 보인다 Files아니라 예 FileOutputStreams.

File(String parent, String child)당신이 쉽게 스와핑을 허용, 파일 경로에서 별도로 디렉토리 경로를 구축하는 경우 생성자는 도움이 될 수 있습니다.

대안은 다른 디렉토리에서 Java를 실행하도록 스크립트를 설정하거나 아래 제안 된대로 JNI 기본 코드 사용하는 것 입니다.

관련 Sun 버그 는 2008 년 "수정되지 않음"으로 종료되었습니다.


12
나는 자바와 C # 사이에서 단 하나의 차이점을 발견했다고 생각하지 않는다. "이 자바 사람들은 그들이 무엇을하고 있는지 확실히 알고있다"
Jake

2
자바가 "이 디렉토리에서 시작 ..."이라는 매개 변수를 가지고 있지 않다는 것을 믿기
어렵다

5
Java의 방어 (그리고 나는이 기능을 원하는 유닉스 사람입니다 ...) ... OS의 세부 사항에 무관심한 VM입니다. 일부 운영 체제에서는 "현재 작업 디렉토리"관용구를 사용할 수 없습니다.
Tony K.

4
Java에 공평하기 위해서는 먼저해야했지만 C #은 많은 영역에서 실수를 통해 배울 수 있다는 이점이있었습니다.
Ryan The Leach

3
@VolkerSeibt : 추가 조사에서 user.dir은 처음에 테스트 한 클래스를 포함하여 일부 클래스에서만 작동하는 것으로 보입니다. new FileOutputStream("foo.txt").close();프로그램이 user.dir을 변경하더라도 원래 작업 디렉토리에 파일을 작성합니다.
Michael Myers

37

ProcessBuilder로 레거시 프로그램을 실행 하면 작업 디렉토리 를 지정할 수 있습니다 .


1
의 경로는 내가 선택한 경로입니다. 다음과 같이 다른 작업 디렉토리에서 실행 파일을 실행할 수있었습니다. File WorkingDir = new File ( "C : \\ path \\ to \\ working \\ dir \\"); ProcessBuilder pBuilder = 새 ProcessBuilder ( "C : \\ path \\ to \\ working \\ dir \\ executable.exe"); pBuilder.directory (WorkingDir); 프로세스 p = pBuilder.start ();
CatsAndCode

29

시스템 프로퍼티 "으로 user.dir"을 사용하여이 작업을 수행 할 수있는 방법은. 이해해야 할 중요한 부분은 getAbsoluteFile ()을 호출해야하며 (아래 참조) 그렇지 않으면 상대 경로가 기본 "user.dir"값 에 대해 결정됩니다 .

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");
    }
}

3
절대 경로가 중요합니다
HackNone

5
그러나 현재 작업 디렉토리는 변경하지 않습니다. 만 값 user.dir. 절대 경로가 중요하다는 사실이이를 증명합니다.
Lorne의 후작

18

JNA / JNI를 사용하여 libc를 호출하여 PWD를 변경할 수 있습니다. JRuby를들는 POSIX를 만들기위한 편리한 자바 라이브러리가 전화 통화를 JNA-POSIX 여기입니다 받는다는 정보

여기 에서 그 사용 예를 볼 수 있습니다 (Clojure 코드, 죄송합니다). chdirToRoot 함수를보십시오


1
jna-posix의 최신 버전이없는 것 같습니다. 나는 github.com/pbiggar/jnr-posix를 포크하고 추가 했습니다 . 이것으로 PWD를 변경할 수 있음을 확인할 수 있습니다.
Paul Biggar

예. 죄송합니다, 해당 파일을 리팩토링하고 파일에 연결된이 답변을 잊어 버렸습니다. 결정된.
Allen Rohner 2013

이 작업을 수행 할 수 있지만, 당신은 또한 변경되지 않는 경우 user.dir시스템 등록 정보를 다음 File.getAbsolutePath()에 대해 해결할 user.dir운영 체제에 대한 파일 결의의 경로 이름이 디렉토리를 작업하는 동안,.
Morrie

jnr-posix를 사용하여 원래의 질문과 관련하여 Java에서 현재 작업 디렉토리를 어떻게 변경할 수 있습니까? chdir 메소드를 사용하려면 어떤 클래스를 만들어야합니까? 주어진 Clojure 예제를 실제로 이해하지 못했습니다. 미리 감사드립니다.
Sam Saint-Pettersen

12

언급했듯이 JVM의 CWD를 변경할 수는 없지만 Runtime.exec ()를 사용하여 다른 프로세스를 시작하려는 경우 작업 디렉토리를 지정할 수있는 오버로드 된 메소드를 사용할 수 있습니다. 이것은 실제로 다른 디렉토리에서 Java 프로그램을 실행하기위한 것이 아니라 Perl 스크립트와 같은 다른 프로그램을 실행해야하는 경우가 많을 때 JVM의 작업 디렉토리를 변경하지 않고 해당 스크립트의 작업 디렉토리를 지정할 수 있습니다.

Runtime.exec javadocs를 참조하십시오.

구체적으로 특별히,

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

dir하위 프로세스를 실행할 작업 디렉토리는 어디에 있습니까?


1
이 답변은 허용 된 답변 ( "순수한 Java에는 신뢰할 수있는 방법이 없습니다"로 시작)보다 나은 답변 인 것 같습니다. 이 답변이 승인 된 답변으로 간주되도록 탄원하는 방법이 있습니까?
John

11

올바르게 이해하면 Java 프로그램은 현재 환경 변수 의 사본 으로 시작 합니다. 변경 사항 System.setProperty(String, String)은 원래 환경 변수가 아니라 사본을 수정합니다. 이것이 썬이 왜이 행동을 선택했는지에 대한 철저한 이유를 제공하지는 않지만 아마도 약간의 빛을 비추고 있습니다 ...


2
환경 변수와 속성을 혼합 한 것 같습니다. 전자는 OS에서 상속되는 반면 후자는을 사용하여 명령 줄에서 정의 할 수 있습니다 -D. 그러나 JVM 시작 user.dir에서 OS에서 복사하여 미리 정의 된 속성을 나중에 변경해도 도움이되지 않는다는 데 동의합니다 .
maaartinus

변경이 user.dir영향을 File.getAbsolutePath()하고 File.getCanonicalPath()있지만 파일을 액세스 할 때 파일 경로 이름이 해결 방법을 지시 작업 디렉토리의 OS의 생각.
Morrie

5

작업 디렉토리는 운영 체제 기능입니다 (프로세스가 시작될 때 설정 됨). 왜 자신의 시스템 속성 ( -Dsomeprop=/my/path)을 전달하고 코드에서 파일의 부모로 사용하지 않습니까?

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

코드에는 하드 코딩 된 파일 경로가 포함되어 있고 작업 할 상위 디렉토리를 지정하지 않은 하드 코딩 된 생성자를 사용하기 때문입니다. Atleast, 그것이 내가 가진 상황 :)
David Mann

4

더 현명하고 쉬운 방법은 코드를 변경하여 파일을 현재 작업 디렉토리에 있다고 가정하는 대신 파일을 여는 대신 파일과 같은 new File("blah.txt")경로를 직접 작성하는 것입니다.

사용자가 기본 디렉토리를 전달하고 구성 파일에서 읽은 user.dir후 다른 특성을 찾을 수없는 경우로 돌아가 십시오. 환경 변수가 작동합니다.


2

나는 호출을 시도했다

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

작동하는 것 같습니다. 그러나

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

FileNotFoundException그래도 던져

myFile.getAbsolutePath()

올바른 경로를 보여줍니다. 나는 이것을 읽었다 . 문제는 다음과 같습니다.

  • Java는 새로운 설정으로 현재 디렉토리를 알고 있습니다.
  • 그러나 파일 처리는 운영 체제에서 수행됩니다. 불행히도 새로운 설정된 현재 디렉토리를 알지 못합니다.

해결책은 다음과 같습니다.

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

JVM에 알려진 현재 디렉토리를 사용하여 파일 오브젝트를 절대 오브젝트로 작성합니다. 그러나 해당 코드는 사용 된 클래스에 존재해야하며 재사용 코드를 변경해야합니다.

~~~~ JcHartmut


"파일 객체를 만듭니다"-예. 그러나 파일 시스템에 파일을 만들지는 않습니다. 그 후에 file.createNewFile ()을 사용하는 것을 잊었습니다.
Gangnus

2

당신이 사용할 수있는

새 파일 ( "상대 / 경로") .getAbsoluteFile ()

System.setProperty ( "user.dir", "/ some / directory")

System.setProperty("user.dir", "C:/OtherProject");
File file = new File("data/data.csv").getAbsoluteFile();
System.out.println(file.getPath());

인쇄합니다

C:\OtherProject\data\data.csv

1
이 동작은 Java 11에서 변경되었습니다 ( bugs.openjdk.java.net/browse/JDK-8202127 참조) . 그들은 사용하지 않는 것이 좋습니다System.setProperty("user.dir", "/some/directory")
Martin

0

이 질문에 대한 다른 가능한 대답은 파일을 여는 이유에 따라 달라질 수 있습니다. 이 파일은 특성 파일입니까, 아니면 응용 프로그램과 관련된 구성이있는 파일입니까?

이 경우 클래스 경로 로더를 통해 파일을로드하려고하면 Java가 액세스 할 수있는 모든 파일을로드 할 수 있습니다.


0

쉘에서 명령을 실행하면 "java -cp"와 같은 것을 작성하고 ":"로 구분하여 원하는 디렉토리를 추가 할 수 있습니다. java가 한 디렉토리에서 무언가를 찾지 못하면 다른 디렉토리에서 찾으십시오. 내가하는 일입니다.


0

JNI 또는 JNA를 사용하여 프로세스의 실제 작업 디렉토리를 변경할 수 있습니다.

JNI 를 사용하면 기본 기능을 사용하여 디렉토리를 설정할 수 있습니다. POSIX 방법은 chdir()입니다. Windows에서는을 사용할 수 있습니다 SetCurrentDirectory().

JNA를 사용 하면 기본 기능을 Java 바인더로 랩핑 할 수 있습니다.

Windows의 경우 :

private static interface MyKernel32 extends Library {
    public MyKernel32 INSTANCE = (MyKernel32) Native.loadLibrary("Kernel32", MyKernel32.class);

    /** BOOL SetCurrentDirectory( LPCTSTR lpPathName ); */
    int SetCurrentDirectoryW(char[] pathName);
}

POSIX 시스템의 경우 :

private interface MyCLibrary extends Library {
    MyCLibrary INSTANCE = (MyCLibrary) Native.loadLibrary("c", MyCLibrary.class);

    /** int chdir(const char *path); */
    int chdir( String path );
}

-1

FileSystemView 사용

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);

import javax.swing.filechooser.FileSystemView;
Borneq

1
이 답변은 질문과 관련이 없습니다.
Aaron Digulla 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.