Java에서 경로를 결합하는 방법은 무엇입니까?


답변:


407

모든 것을 문자열 기반으로 유지하기보다는 파일 시스템 경로를 나타내도록 설계된 클래스를 사용해야합니다.

Java 7 또는 Java 8을 사용하는 경우 java.nio.file.Path; Path.resolve한 경로를 다른 경로 또는 문자열과 결합하는 데 사용할 수 있습니다. Paths헬퍼 클래스도 유용하다. 예를 들면 다음과 같습니다.

Path path = Paths.get("foo", "bar", "baz.txt");

Java-7 이전 환경을 수용해야하는 경우 다음 java.io.File과 같이 사용할 수 있습니다 .

File baseDirectory = new File("foo");
File subDirectory = new File(baseDirectory, "bar");
File fileInDirectory = new File(subDirectory, "baz.txt");

나중에 문자열로 다시 원하면을 호출 할 수 있습니다 getPath(). 실제로, 당신이 정말로 모방 Path.Combine하고 싶다면 다음과 같이 쓸 수 있습니다.

public static String combine(String path1, String path2)
{
    File file1 = new File(path1);
    File file2 = new File(file1, path2);
    return file2.getPath();
}

10
절대 경로를주의하십시오. .NET 버전은 절대 경로 인 path2경우을 (를 무시 path1) 반환 path2합니다. Java 버전은 선행을 삭제 /하거나 \ 상대 경로로 취급합니다.
finnw

23
@Matthew-디렉토리는 파일이므로 파일의 내용은 해당 디렉토리의 자식, 디스크에서의 위치, 권한 등을 정의합니다.
Dónal

7
@ Hugo : 그래서 그것은 전체 두 개체를 낭비 합니까? 충격적인! 솔직히 말해서 꽤 깨끗해 보입니다 ... File 클래스에서 상대 파일 이름 의 논리 를 유지합니다 .
Jon Skeet

1
@modosansreves :를보십시오 File.getCanonicalPath.
Jon Skeet

1
@SargeBorsch : 음 C #은 언어 일뿐입니다. File원하는 경우 C #에서 자신과 동등한 것을 쉽게 만들 수 있습니다 . (나는 당신이 존재한다는 File것이 내가 동의하는 이익 이라는 것을 의미한다고 가정합니다 .)
Jon Skeet

118

Java 7에서는 다음을 사용해야합니다 resolve.

Path newPath = path.resolve(childPath);

NIO2 Path 클래스는 불필요하게 다른 API를 사용하여 File에 약간 중복되는 것처럼 보이지만 실제로는 우아하고 강력합니다.

그 주 Paths.get()과부하가를 복용하지 않습니다 (다른 사람에 의해 제안) Path, 그리고 일을하는 것은 Paths.get(path.toString(), childPath)같은 것이 아니다 resolve(). 로부터 Paths.get()문서 :

이 방법은 매우 편리하지만이 방법을 사용하면 기본 FileSystem에 대한 가정 된 참조를 나타내며 호출 코드의 유틸리티가 제한됩니다. 따라서 유연한 재사용을 목적으로하는 라이브러리 코드에는 사용해서는 안됩니다. 보다 유연한 대안은 기존 경로 인스턴스를 다음과 같은 앵커로 사용하는 것입니다.

Path dir = ...
Path path = dir.resolve("file");

자매 기능 resolve은 우수합니다 relativize.

Path childPath = path.relativize(newPath);

42

주요 대답은 File 객체를 사용하는 것입니다. 그러나 Commons IO 에는 concat () 메소드 와 같은 이런 종류의 작업을 수행 할 수있는 FilenameUtils 클래스 가 있습니다 .



JSF와 같은 작업을 수행하는 경우 모든 경로가 문자열 기반이므로 문자열 기반으로 유지하려고합니다.
DanielK

17

Jon의 원래 답변 이후 오랜 시간을 알고 있었지만 OP와 비슷한 요구 사항이있었습니다.

Jon의 솔루션을 확장하여 다음을 생각해 냈습니다. 하나 이상의 경로 세그먼트를 사용하면 많은 경로 세그먼트를 사용하여 처리 할 수 ​​있습니다.

용법

Path.combine("/Users/beardtwizzle/");
Path.combine("/", "Users", "beardtwizzle");
Path.combine(new String[] { "/", "Users", "beardtwizzle", "arrayUsage" });

비슷한 문제를 가진 다른 사람들을 위해 여기에 코드를 작성하십시오

public class Path {
    public static String combine(String... paths)
    {
        File file = new File(paths[0]);

        for (int i = 1; i < paths.length ; i++) {
            file = new File(file, paths[i]);
        }

        return file.getPath();
    }
}

12

플랫폼 독립적 접근 (File.separator를 사용합니다. 즉, 작동하는 코드는 운영 체제에 따라 다릅니다.

java.nio.file.Paths.get(".", "path", "to", "file.txt")
// relative unix path: ./path/to/file.txt
// relative windows path: .\path\to\filee.txt

java.nio.file.Paths.get("/", "path", "to", "file.txt")
// absolute unix path: /path/to/filee.txt
// windows network drive path: \\path\to\file.txt

java.nio.file.Paths.get("C:", "path", "to", "file.txt")
// absolute windows path: C:\path\to\file.txt

11

JodaStephen의 답변을 향상시키기 위해 Apache Commons IO에는 FilenameUtils가 있습니다. 예 (Linux) :

assert org.apache.commons.io.FilenameUtils.concat("/home/bob", "work\\stuff.log") == "/home/bob/work/stuff.log"

플랫폼 독립적이며 시스템에 필요한 구분 기호를 생성합니다.


2

다음은 여러 경로 부품과 가장자리 조건을 처리하는 솔루션입니다.

public static String combinePaths(String ... paths)
{
  if ( paths.length == 0)
  {
    return "";
  }

  File combined = new File(paths[0]);

  int i = 1;
  while ( i < paths.length)
  {
    combined = new File(combined, paths[i]);
    ++i;
  }

  return combined.getPath();
}


1

아마도 파티에 늦었지만 이것에 대한 나의 의견을 나누고 싶었습니다. 빌더 패턴을 사용하고 있으며 편리하게 연결된 append통화를 허용 합니다. Path객체 작업도 지원하도록 쉽게 확장 할 수 있습니다 .

public class Files  {
    public static class PathBuilder {
        private File file;

        private PathBuilder ( File root ) {
            file = root;
        }

        private PathBuilder ( String root ) {
            file = new File(root);
        }

        public PathBuilder append ( File more ) {
            file = new File(file, more.getPath()) );
            return this;
        }

        public PathBuilder append ( String more ) {
            file = new File(file, more);
            return this;
        }

        public File buildFile () {
            return file;
        }
    }

    public static PathBuilder buildPath ( File root ) {
        return new PathBuilder(root);
    }

    public static PathBuilder buildPath ( String root ) {
        return new PathBuilder(root);
    }
}

사용 예 :

File root = File.listRoots()[0];
String hello = "hello";
String world = "world";
String filename = "warez.lha"; 

File file = Files.buildPath(root).append(hello).append(world)
              .append(filename).buildFile();
String absolute = file.getAbsolutePath();

결과 absolute는 다음과 같습니다.

/hello/world/warez.lha

또는 아마도 :

A:\hello\world\warez.lha

1

이것은 Java 8에서도 작동합니다.

Path file = Paths.get("Some path");
file = Paths.get(file + "Some other path");

0

이 솔루션은 String [] 배열에서 경로 조각을 결합하기위한 인터페이스를 제공합니다. 그것은 사용 java.io.File.File (문자열 부모, 문자열 아이) :

    public static joinPaths(String[] fragments) {
        String emptyPath = "";
        return buildPath(emptyPath, fragments);
    }

    private static buildPath(String path, String[] fragments) {
        if (path == null || path.isEmpty()) {
            path = "";
        }

        if (fragments == null || fragments.length == 0) {
            return "";
        }

        int pathCurrentSize = path.split("/").length;
        int fragmentsLen = fragments.length;

        if (pathCurrentSize <= fragmentsLen) {
            String newPath = new File(path, fragments[pathCurrentSize - 1]).toString();
            path = buildPath(newPath, fragments);
        }

        return path;
    }

그럼 당신은 할 수 있습니다 :

String[] fragments = {"dir", "anotherDir/", "/filename.txt"};
String path = joinPaths(fragments);

보고:

"/dir/anotherDir/filename.txt"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.